diff --git a/CMakeLists.txt b/CMakeLists.txt index ffbcf5b67..a1a13ef6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,11 @@ SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH "Path the tool executables are installed to." ) -SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools") +IF (CMAKE_BUILD_TYPE STREQUAL "Release") + SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools") +ELSE() + SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools") +ENDIF() # Only generate this target if no higher-level project already has IF (NOT TARGET uninstall) diff --git a/code/ACLoader.cpp b/code/ACLoader.cpp index 5b7b6a61d..8e62da442 100644 --- a/code/ACLoader.cpp +++ b/code/ACLoader.cpp @@ -89,6 +89,9 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // read a string (may be enclosed in double quotation marks). buffer must point to " #define AI_AC_GET_STRING(out) \ + if (*buffer == '\0') { \ + throw DeadlyImportError("AC3D: Unexpected EOF in string"); \ + } \ ++buffer; \ const char* sz = buffer; \ while ('\"' != *buffer) \ @@ -293,7 +296,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) SkipSpaces(&buffer); unsigned int t = strtoul10(buffer,&buffer); - if (t >= std::numeric_limits::max() / sizeof(aiVector3D)) { + if (t >= AI_MAX_ALLOC(aiVector3D)) { throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); } obj.vertices.reserve(t); @@ -349,8 +352,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) { if(!GetNextLine()) { - DefaultLogger::get()->error("AC3D: Unexpected EOF: surface is incomplete"); - break; + throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete"); } if (TokenMatch(buffer,"mat",3)) { @@ -585,9 +587,19 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, // allocate storage for vertices and normals mesh->mNumFaces = (*cit).first; + if (mesh->mNumFaces == 0) { + throw DeadlyImportError("AC3D: No faces"); + } else if (mesh->mNumFaces > AI_MAX_ALLOC(aiFace)) { + throw DeadlyImportError("AC3D: Too many faces, would run out of memory"); + } aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; mesh->mNumVertices = (*cit).second; + if (mesh->mNumVertices == 0) { + throw DeadlyImportError("AC3D: No vertices"); + } else if (mesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) { + throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); + } aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; unsigned int cur = 0; diff --git a/code/BlenderScene.h b/code/BlenderScene.h index ca750bb84..25c301891 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -103,7 +103,7 @@ struct Image; // ------------------------------------------------------------------------------- struct ID : ElemBase { - char name[24] WARN; + char name[1024] WARN; short flag; }; diff --git a/code/BoostWorkaround/boost/LICENSE_1_0.txt b/code/BoostWorkaround/boost/LICENSE_1_0.txt index 30aac2cf4..127a5bc39 100644 --- a/code/BoostWorkaround/boost/LICENSE_1_0.txt +++ b/code/BoostWorkaround/boost/LICENSE_1_0.txt @@ -1,23 +1,23 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/code/BoostWorkaround/boost/foreach.hpp b/code/BoostWorkaround/boost/foreach.hpp index 5b5df6a36..404d325c6 100644 --- a/code/BoostWorkaround/boost/foreach.hpp +++ b/code/BoostWorkaround/boost/foreach.hpp @@ -1,99 +1,99 @@ - -#ifndef BOOST_FOREACH - -/////////////////////////////////////////////////////////////////////////////// -// A stripped down version of FOREACH for -// illustration purposes. NOT FOR GENERAL USE. -// For a complete implementation, see BOOST_FOREACH at -// http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler -// -// Copyright 2004 Eric Niebler. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Adapted to Assimp November 29th, 2008 (Alexander Gessler). -// Added code to handle both const and non-const iterators, simplified some -// parts. -/////////////////////////////////////////////////////////////////////////////// - -namespace boost { -namespace foreach_detail { - -/////////////////////////////////////////////////////////////////////////////// -// auto_any - -struct auto_any_base -{ - operator bool() const { return false; } -}; - -template -struct auto_any : auto_any_base -{ - auto_any(T const& t) : item(t) {} - mutable T item; -}; - -template -T& auto_any_cast(auto_any_base const& any) -{ - return static_cast const&>(any).item; -} - -/////////////////////////////////////////////////////////////////////////////// -// FOREACH helper function - -template -auto_any begin(T const& t) -{ - return t.begin(); -} - -template -auto_any end(T const& t) -{ - return t.end(); -} - -// iterator -template -bool done(auto_any_base const& cur, auto_any_base const& end, T&) -{ - typedef typename T::iterator iter_type; - return auto_any_cast(cur) == auto_any_cast(end); -} - -template -void next(auto_any_base const& cur, T&) -{ - ++auto_any_cast(cur); -} - -template -typename T::reference deref(auto_any_base const& cur, T&) -{ - return *auto_any_cast(cur); -} - -template -typename T::const_reference deref(auto_any_base const& cur, const T&) -{ - return *auto_any_cast(cur); -} - -} // end foreach_detail - -/////////////////////////////////////////////////////////////////////////////// -// FOREACH - -#define BOOST_FOREACH(item, container) \ - if(boost::foreach_detail::auto_any_base const& foreach_magic_b = boost::foreach_detail::begin(container)) {} else \ - if(boost::foreach_detail::auto_any_base const& foreach_magic_e = boost::foreach_detail::end(container)) {} else \ - for(;!boost::foreach_detail::done(foreach_magic_b,foreach_magic_e,container); boost::foreach_detail::next(foreach_magic_b,container)) \ - if (bool ugly_and_unique_break = false) {} else \ - for(item = boost::foreach_detail::deref(foreach_magic_b,container); !ugly_and_unique_break; ugly_and_unique_break = true) - -} // end boost - -#endif + +#ifndef BOOST_FOREACH + +/////////////////////////////////////////////////////////////////////////////// +// A stripped down version of FOREACH for +// illustration purposes. NOT FOR GENERAL USE. +// For a complete implementation, see BOOST_FOREACH at +// http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler +// +// Copyright 2004 Eric Niebler. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Adapted to Assimp November 29th, 2008 (Alexander Gessler). +// Added code to handle both const and non-const iterators, simplified some +// parts. +/////////////////////////////////////////////////////////////////////////////// + +namespace boost { +namespace foreach_detail { + +/////////////////////////////////////////////////////////////////////////////// +// auto_any + +struct auto_any_base +{ + operator bool() const { return false; } +}; + +template +struct auto_any : auto_any_base +{ + auto_any(T const& t) : item(t) {} + mutable T item; +}; + +template +T& auto_any_cast(auto_any_base const& any) +{ + return static_cast const&>(any).item; +} + +/////////////////////////////////////////////////////////////////////////////// +// FOREACH helper function + +template +auto_any begin(T const& t) +{ + return t.begin(); +} + +template +auto_any end(T const& t) +{ + return t.end(); +} + +// iterator +template +bool done(auto_any_base const& cur, auto_any_base const& end, T&) +{ + typedef typename T::iterator iter_type; + return auto_any_cast(cur) == auto_any_cast(end); +} + +template +void next(auto_any_base const& cur, T&) +{ + ++auto_any_cast(cur); +} + +template +typename T::reference deref(auto_any_base const& cur, T&) +{ + return *auto_any_cast(cur); +} + +template +typename T::const_reference deref(auto_any_base const& cur, const T&) +{ + return *auto_any_cast(cur); +} + +} // end foreach_detail + +/////////////////////////////////////////////////////////////////////////////// +// FOREACH + +#define BOOST_FOREACH(item, container) \ + if(boost::foreach_detail::auto_any_base const& foreach_magic_b = boost::foreach_detail::begin(container)) {} else \ + if(boost::foreach_detail::auto_any_base const& foreach_magic_e = boost::foreach_detail::end(container)) {} else \ + for(;!boost::foreach_detail::done(foreach_magic_b,foreach_magic_e,container); boost::foreach_detail::next(foreach_magic_b,container)) \ + if (bool ugly_and_unique_break = false) {} else \ + for(item = boost::foreach_detail::deref(foreach_magic_b,container); !ugly_and_unique_break; ugly_and_unique_break = true) + +} // end boost + +#endif diff --git a/code/BoostWorkaround/boost/format.hpp b/code/BoostWorkaround/boost/format.hpp index e65499a6a..136c76401 100644 --- a/code/BoostWorkaround/boost/format.hpp +++ b/code/BoostWorkaround/boost/format.hpp @@ -1,82 +1,82 @@ - - - -/* DEPRECATED! - use code/TinyFormatter.h instead. - * - * - * */ - -#ifndef AI_BOOST_FORMAT_DUMMY_INCLUDED -#define AI_BOOST_FORMAT_DUMMY_INCLUDED - -#if (!defined BOOST_FORMAT_HPP) || (defined ASSIMP_FORCE_NOBOOST) - -#include -#include -#include - -namespace boost -{ - - - class format - { - public: - format (const std::string& _d) - : d(_d) - { - } - - template - format& operator % (T in) - { - // XXX add replacement for boost::lexical_cast? - - std::ostringstream ss; - ss << in; // note: ss cannot be an rvalue, or the global operator << (const char*) is not called for T == const char*. - chunks.push_back( ss.str()); - return *this; - } - - - operator std::string () const { - std::string res; // pray for NRVO to kick in - - size_t start = 0, last = 0; - - std::vector::const_iterator chunkin = chunks.begin(); - - for ( start = d.find('%');start != std::string::npos; start = d.find('%',last)) { - res += d.substr(last,start-last); - last = start+2; - if (d[start+1] == '%') { - res += "%"; - continue; - } - - if (chunkin == chunks.end()) { - break; - } - - res += *chunkin++; - } - res += d.substr(last); - return res; - } - - private: - std::string d; - std::vector chunks; - }; - - inline std::string str(const std::string& s) { - return s; - } -} - - -#else -# error "format.h was already included" -#endif // -#endif // !! AI_BOOST_FORMAT_DUMMY_INCLUDED - + + + +/* DEPRECATED! - use code/TinyFormatter.h instead. + * + * + * */ + +#ifndef AI_BOOST_FORMAT_DUMMY_INCLUDED +#define AI_BOOST_FORMAT_DUMMY_INCLUDED + +#if (!defined BOOST_FORMAT_HPP) || (defined ASSIMP_FORCE_NOBOOST) + +#include +#include +#include + +namespace boost +{ + + + class format + { + public: + format (const std::string& _d) + : d(_d) + { + } + + template + format& operator % (T in) + { + // XXX add replacement for boost::lexical_cast? + + std::ostringstream ss; + ss << in; // note: ss cannot be an rvalue, or the global operator << (const char*) is not called for T == const char*. + chunks.push_back( ss.str()); + return *this; + } + + + operator std::string () const { + std::string res; // pray for NRVO to kick in + + size_t start = 0, last = 0; + + std::vector::const_iterator chunkin = chunks.begin(); + + for ( start = d.find('%');start != std::string::npos; start = d.find('%',last)) { + res += d.substr(last,start-last); + last = start+2; + if (d[start+1] == '%') { + res += "%"; + continue; + } + + if (chunkin == chunks.end()) { + break; + } + + res += *chunkin++; + } + res += d.substr(last); + return res; + } + + private: + std::string d; + std::vector chunks; + }; + + inline std::string str(const std::string& s) { + return s; + } +} + + +#else +# error "format.h was already included" +#endif // +#endif // !! AI_BOOST_FORMAT_DUMMY_INCLUDED + diff --git a/code/BoostWorkaround/boost/lexical_cast.hpp b/code/BoostWorkaround/boost/lexical_cast.hpp index 7724e4607..af91b011f 100644 --- a/code/BoostWorkaround/boost/lexical_cast.hpp +++ b/code/BoostWorkaround/boost/lexical_cast.hpp @@ -1,26 +1,26 @@ -/// A quick replacement for boost::lexical_cast for all the Boost haters out there - -#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST -#define __AI_BOOST_WORKAROUND_LEXICAL_CAST - -#include - -namespace boost -{ - - /// A quick replacement for boost::lexical_cast - should work for all types a stringstream can handle - template - TargetType lexical_cast( const SourceType& source) - { - std::stringstream stream; - TargetType result; - - stream << source; - stream >> result; - return result; - } - -} // namespace boost - -#endif // __AI_BOOST_WORKAROUND_LEXICAL_CAST - +/// A quick replacement for boost::lexical_cast for all the Boost haters out there + +#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST +#define __AI_BOOST_WORKAROUND_LEXICAL_CAST + +#include + +namespace boost +{ + + /// A quick replacement for boost::lexical_cast - should work for all types a stringstream can handle + template + TargetType lexical_cast( const SourceType& source) + { + std::stringstream stream; + TargetType result; + + stream << source; + stream >> result; + return result; + } + +} // namespace boost + +#endif // __AI_BOOST_WORKAROUND_LEXICAL_CAST + diff --git a/code/BoostWorkaround/boost/make_shared.hpp b/code/BoostWorkaround/boost/make_shared.hpp index b7b29caa5..d1abb1be6 100644 --- a/code/BoostWorkaround/boost/make_shared.hpp +++ b/code/BoostWorkaround/boost/make_shared.hpp @@ -1,57 +1,57 @@ - -// please note that this replacement implementation does not -// provide the performance benefit of the original, which -// makes only one allocation as opposed to two allocations -// (smart pointer counter and payload) which are usually -// required if object and smart pointer are constructed -// independently. - -#ifndef INCLUDED_AI_BOOST_MAKE_SHARED -#define INCLUDED_AI_BOOST_MAKE_SHARED - - -namespace boost { - - template - shared_ptr make_shared() { - return shared_ptr(new T()); - } - - template - shared_ptr make_shared(const T0& t0) { - return shared_ptr(new T(t0)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1) { - return shared_ptr(new T(t0,t1)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2) { - return shared_ptr(new T(t0,t1,t2)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { - return shared_ptr(new T(t0,t1,t2,t3)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4) { - return shared_ptr(new T(t0,t1,t2,t3,t4)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) { - return shared_ptr(new T(t0,t1,t2,t3,t4,t5)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) { - return shared_ptr(new T(t0,t1,t2,t3,t4,t5,t6)); - } -} - - -#endif + +// please note that this replacement implementation does not +// provide the performance benefit of the original, which +// makes only one allocation as opposed to two allocations +// (smart pointer counter and payload) which are usually +// required if object and smart pointer are constructed +// independently. + +#ifndef INCLUDED_AI_BOOST_MAKE_SHARED +#define INCLUDED_AI_BOOST_MAKE_SHARED + + +namespace boost { + + template + shared_ptr make_shared() { + return shared_ptr(new T()); + } + + template + shared_ptr make_shared(const T0& t0) { + return shared_ptr(new T(t0)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1) { + return shared_ptr(new T(t0,t1)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2) { + return shared_ptr(new T(t0,t1,t2)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { + return shared_ptr(new T(t0,t1,t2,t3)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4) { + return shared_ptr(new T(t0,t1,t2,t3,t4)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) { + return shared_ptr(new T(t0,t1,t2,t3,t4,t5)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) { + return shared_ptr(new T(t0,t1,t2,t3,t4,t5,t6)); + } +} + + +#endif diff --git a/code/BoostWorkaround/boost/math/common_factor_rt.hpp b/code/BoostWorkaround/boost/math/common_factor_rt.hpp index 46a70a298..f7615f974 100644 --- a/code/BoostWorkaround/boost/math/common_factor_rt.hpp +++ b/code/BoostWorkaround/boost/math/common_factor_rt.hpp @@ -1,37 +1,37 @@ - - -#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP -#define BOOST_MATH_COMMON_FACTOR_RT_HPP - - -namespace boost { -namespace math { - -// TODO: use binary GCD for unsigned integers .... -template < typename IntegerType > -IntegerType gcd( IntegerType a, IntegerType b ) -{ - const IntegerType zero = (IntegerType)0; - while ( true ) - { - if ( a == zero ) - return b; - b %= a; - - if ( b == zero ) - return a; - a %= b; - } -} - -template < typename IntegerType > -IntegerType lcm( IntegerType a, IntegerType b ) -{ - const IntegerType t = gcd (a,b); - if (!t)return t; - return a / t * b; -} - -}} - -#endif + + +#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP +#define BOOST_MATH_COMMON_FACTOR_RT_HPP + + +namespace boost { +namespace math { + +// TODO: use binary GCD for unsigned integers .... +template < typename IntegerType > +IntegerType gcd( IntegerType a, IntegerType b ) +{ + const IntegerType zero = (IntegerType)0; + while ( true ) + { + if ( a == zero ) + return b; + b %= a; + + if ( b == zero ) + return a; + a %= b; + } +} + +template < typename IntegerType > +IntegerType lcm( IntegerType a, IntegerType b ) +{ + const IntegerType t = gcd (a,b); + if (!t)return t; + return a / t * b; +} + +}} + +#endif diff --git a/code/BoostWorkaround/boost/noncopyable.hpp b/code/BoostWorkaround/boost/noncopyable.hpp index 7deb935fb..7770bdbd3 100644 --- a/code/BoostWorkaround/boost/noncopyable.hpp +++ b/code/BoostWorkaround/boost/noncopyable.hpp @@ -1,36 +1,36 @@ -// Boost noncopyable.hpp header file --------------------------------------// - -// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/utility for documentation. - -#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED -#define BOOST_NONCOPYABLE_HPP_INCLUDED - -namespace boost { - -// Private copy constructor and copy assignment ensure classes derived from -// class noncopyable cannot be copied. - -// Contributed by Dave Abrahams - -namespace noncopyable_ // protection from unintended ADL -{ - class noncopyable - { - protected: - noncopyable() {} - ~noncopyable() {} - private: // emphasize the following members are private - noncopyable( const noncopyable& ); - const noncopyable& operator=( const noncopyable& ); - }; -} - -typedef noncopyable_::noncopyable noncopyable; - -} // namespace boost - -#endif // BOOST_NONCOPYABLE_HPP_INCLUDED +// Boost noncopyable.hpp header file --------------------------------------// + +// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/utility for documentation. + +#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED +#define BOOST_NONCOPYABLE_HPP_INCLUDED + +namespace boost { + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +// Contributed by Dave Abrahams + +namespace noncopyable_ // protection from unintended ADL +{ + class noncopyable + { + protected: + noncopyable() {} + ~noncopyable() {} + private: // emphasize the following members are private + noncopyable( const noncopyable& ); + const noncopyable& operator=( const noncopyable& ); + }; +} + +typedef noncopyable_::noncopyable noncopyable; + +} // namespace boost + +#endif // BOOST_NONCOPYABLE_HPP_INCLUDED diff --git a/code/BoostWorkaround/boost/pointer_cast.hpp b/code/BoostWorkaround/boost/pointer_cast.hpp index 1083f599e..6e532ebdd 100644 --- a/code/BoostWorkaround/boost/pointer_cast.hpp +++ b/code/BoostWorkaround/boost/pointer_cast.hpp @@ -1,45 +1,45 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2005. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_POINTER_CAST_HPP -#define BOOST_POINTER_CAST_HPP - -namespace boost { - -//static_pointer_cast overload for raw pointers -template -inline T* static_pointer_cast(U *ptr) -{ - return static_cast(ptr); -} - -//dynamic_pointer_cast overload for raw pointers -template -inline T* dynamic_pointer_cast(U *ptr) -{ - return dynamic_cast(ptr); -} - -//const_pointer_cast overload for raw pointers -template -inline T* const_pointer_cast(U *ptr) -{ - return const_cast(ptr); -} - -//reinterpret_pointer_cast overload for raw pointers -template -inline T* reinterpret_pointer_cast(U *ptr) -{ - return reinterpret_cast(ptr); -} - -} // namespace boost - -#endif //BOOST_POINTER_CAST_HPP +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_POINTER_CAST_HPP +#define BOOST_POINTER_CAST_HPP + +namespace boost { + +//static_pointer_cast overload for raw pointers +template +inline T* static_pointer_cast(U *ptr) +{ + return static_cast(ptr); +} + +//dynamic_pointer_cast overload for raw pointers +template +inline T* dynamic_pointer_cast(U *ptr) +{ + return dynamic_cast(ptr); +} + +//const_pointer_cast overload for raw pointers +template +inline T* const_pointer_cast(U *ptr) +{ + return const_cast(ptr); +} + +//reinterpret_pointer_cast overload for raw pointers +template +inline T* reinterpret_pointer_cast(U *ptr) +{ + return reinterpret_cast(ptr); +} + +} // namespace boost + +#endif //BOOST_POINTER_CAST_HPP diff --git a/code/BoostWorkaround/boost/scoped_array.hpp b/code/BoostWorkaround/boost/scoped_array.hpp index 7b1d8cc42..fb1b11544 100644 --- a/code/BoostWorkaround/boost/scoped_array.hpp +++ b/code/BoostWorkaround/boost/scoped_array.hpp @@ -1,79 +1,79 @@ - -#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED -#define __AI_BOOST_SCOPED_ARRAY_INCLUDED - -#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED - -namespace boost { - -// small replacement for boost::scoped_array -template -class scoped_array -{ -public: - - // provide a default construtctor - scoped_array() - : ptr(0) - { - } - - // construction from an existing heap object of type T - scoped_array(T* _ptr) - : ptr(_ptr) - { - } - - // automatic destruction of the wrapped object at the - // end of our lifetime - ~scoped_array() - { - delete[] ptr; - } - - inline T* get() - { - return ptr; - } - - inline T* operator-> () - { - return ptr; - } - - inline void reset (T* t = 0) - { - delete[] ptr; - ptr = t; - } - - T & operator[](std::ptrdiff_t i) const - { - return ptr[i]; - } - - void swap(scoped_array & b) - { - std::swap(ptr, b.ptr); - } - -private: - - // encapsulated object pointer - T* ptr; - -}; - -template -inline void swap(scoped_array & a, scoped_array & b) -{ - a.swap(b); -} - -} // end of namespace boost - -#else -# error "scoped_array.h was already included" -#endif -#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED - + +#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED +#define __AI_BOOST_SCOPED_ARRAY_INCLUDED + +#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED + +namespace boost { + +// small replacement for boost::scoped_array +template +class scoped_array +{ +public: + + // provide a default construtctor + scoped_array() + : ptr(0) + { + } + + // construction from an existing heap object of type T + scoped_array(T* _ptr) + : ptr(_ptr) + { + } + + // automatic destruction of the wrapped object at the + // end of our lifetime + ~scoped_array() + { + delete[] ptr; + } + + inline T* get() + { + return ptr; + } + + inline T* operator-> () + { + return ptr; + } + + inline void reset (T* t = 0) + { + delete[] ptr; + ptr = t; + } + + T & operator[](std::ptrdiff_t i) const + { + return ptr[i]; + } + + void swap(scoped_array & b) + { + std::swap(ptr, b.ptr); + } + +private: + + // encapsulated object pointer + T* ptr; + +}; + +template +inline void swap(scoped_array & a, scoped_array & b) +{ + a.swap(b); +} + +} // end of namespace boost + +#else +# error "scoped_array.h was already included" +#endif +#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED + diff --git a/code/BoostWorkaround/boost/scoped_ptr.hpp b/code/BoostWorkaround/boost/scoped_ptr.hpp index 615db640d..80c394def 100644 --- a/code/BoostWorkaround/boost/scoped_ptr.hpp +++ b/code/BoostWorkaround/boost/scoped_ptr.hpp @@ -1,79 +1,79 @@ - -#ifndef __AI_BOOST_SCOPED_PTR_INCLUDED -#define __AI_BOOST_SCOPED_PTR_INCLUDED - -#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED - -namespace boost { - -// small replacement for boost::scoped_ptr -template -class scoped_ptr -{ -public: - - // provide a default construtctor - scoped_ptr() - : ptr(0) - { - } - - // construction from an existing heap object of type T - scoped_ptr(T* _ptr) - : ptr(_ptr) - { - } - - // automatic destruction of the wrapped object at the - // end of our lifetime - ~scoped_ptr() - { - delete ptr; - } - - inline T* get() const - { - return ptr; - } - - inline operator T*() - { - return ptr; - } - - inline T* operator-> () - { - return ptr; - } - - inline void reset (T* t = 0) - { - delete ptr; - ptr = t; - } - - void swap(scoped_ptr & b) - { - std::swap(ptr, b.ptr); - } - -private: - - // encapsulated object pointer - T* ptr; - -}; - -template -inline void swap(scoped_ptr & a, scoped_ptr & b) -{ - a.swap(b); -} - -} // end of namespace boost - -#else -# error "scoped_ptr.h was already included" -#endif -#endif // __AI_BOOST_SCOPED_PTR_INCLUDED - + +#ifndef __AI_BOOST_SCOPED_PTR_INCLUDED +#define __AI_BOOST_SCOPED_PTR_INCLUDED + +#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED + +namespace boost { + +// small replacement for boost::scoped_ptr +template +class scoped_ptr +{ +public: + + // provide a default construtctor + scoped_ptr() + : ptr(0) + { + } + + // construction from an existing heap object of type T + scoped_ptr(T* _ptr) + : ptr(_ptr) + { + } + + // automatic destruction of the wrapped object at the + // end of our lifetime + ~scoped_ptr() + { + delete ptr; + } + + inline T* get() const + { + return ptr; + } + + inline operator T*() + { + return ptr; + } + + inline T* operator-> () + { + return ptr; + } + + inline void reset (T* t = 0) + { + delete ptr; + ptr = t; + } + + void swap(scoped_ptr & b) + { + std::swap(ptr, b.ptr); + } + +private: + + // encapsulated object pointer + T* ptr; + +}; + +template +inline void swap(scoped_ptr & a, scoped_ptr & b) +{ + a.swap(b); +} + +} // end of namespace boost + +#else +# error "scoped_ptr.h was already included" +#endif +#endif // __AI_BOOST_SCOPED_PTR_INCLUDED + diff --git a/code/BoostWorkaround/boost/shared_array.hpp b/code/BoostWorkaround/boost/shared_array.hpp index 2d068d556..9847d9f82 100644 --- a/code/BoostWorkaround/boost/shared_array.hpp +++ b/code/BoostWorkaround/boost/shared_array.hpp @@ -1,228 +1,228 @@ - -#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY -#define INCLUDED_AI_BOOST_SHARED_ARRAY - -#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED - -// ------------------------------ -// Internal stub -namespace boost { - namespace array_detail { - class controller { - public: - - controller() - : cnt(1) - {} - - public: - - template - controller* decref(T* pt) { - if (--cnt <= 0) { - delete this; - delete[] pt; - } - return NULL; - } - - controller* incref() { - ++cnt; - return this; - } - - long get() const { - return cnt; - } - - private: - long cnt; - }; - - struct empty {}; - - template - struct is_convertible_stub { - - struct yes {char s[1];}; - struct no {char s[2];}; - - static yes foo(DEST*); - static no foo(...); - - enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; - }; - - template struct enable_if {}; - template <> struct enable_if { - typedef empty result; - }; - - template - struct is_convertible : public enable_if::result > { - }; - } - -// ------------------------------ -// Small replacement for boost::shared_array, not threadsafe because no -// atomic reference counter is in use. -// ------------------------------ -template -class shared_array -{ - template friend class shared_array; - - template friend bool operator== (const shared_array& a, const shared_array& b); - template friend bool operator!= (const shared_array& a, const shared_array& b); - template friend bool operator< (const shared_array& a, const shared_array& b); - -public: - - typedef T element_type; - -public: - - // provide a default constructor - shared_array() - : ptr() - , ctr(NULL) - { - } - - // construction from an existing object of type T - explicit shared_array(T* ptr) - : ptr(ptr) - , ctr(ptr ? new array_detail::controller() : NULL) - { - } - - shared_array(const shared_array& r) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - template - shared_array(const shared_array& r,typename detail::is_convertible::result = detail::empty()) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - // automatic destruction of the wrapped object when all - // references are freed. - ~shared_array() { - if (ctr) { - ctr = ctr->decref(ptr); - } - } - - shared_array& operator=(const shared_array& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - template - shared_array& operator=(const shared_array& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - // pointer access - inline operator T*() { - return ptr; - } - - inline T* operator-> () const { - return ptr; - } - - // standard semantics - inline T* get() { - return ptr; - } - - T& operator[] (std::ptrdiff_t index) const { - return ptr[index]; - } - - inline const T* get() const { - return ptr; - } - - inline operator bool () const { - return ptr != NULL; - } - - inline bool unique() const { - return use_count() == 1; - } - - inline long use_count() const { - return ctr->get(); - } - - inline void reset (T* t = 0) { - if (ctr) { - ctr->decref(ptr); - } - ptr = t; - ctr = ptr?new array_detail::controller():NULL; - } - - void swap(shared_array & b) { - std::swap(ptr, b.ptr); - std::swap(ctr, b.ctr); - } - - -private: - - // encapsulated object pointer - T* ptr; - - // control block - array_detail::controller* ctr; -}; - -template -inline void swap(shared_array & a, shared_array & b) -{ - a.swap(b); -} - -template -bool operator== (const shared_array& a, const shared_array& b) { - return a.ptr == b.ptr; -} -template -bool operator!= (const shared_array& a, const shared_array& b) { - return a.ptr != b.ptr; -} - -template -bool operator< (const shared_array& a, const shared_array& b) { - return a.ptr < b.ptr; -} - - -} // end of namespace boost - -#else -# error "shared_array.h was already included" -#endif -#endif // INCLUDED_AI_BOOST_SHARED_ARRAY + +#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY +#define INCLUDED_AI_BOOST_SHARED_ARRAY + +#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED + +// ------------------------------ +// Internal stub +namespace boost { + namespace array_detail { + class controller { + public: + + controller() + : cnt(1) + {} + + public: + + template + controller* decref(T* pt) { + if (--cnt <= 0) { + delete this; + delete[] pt; + } + return NULL; + } + + controller* incref() { + ++cnt; + return this; + } + + long get() const { + return cnt; + } + + private: + long cnt; + }; + + struct empty {}; + + template + struct is_convertible_stub { + + struct yes {char s[1];}; + struct no {char s[2];}; + + static yes foo(DEST*); + static no foo(...); + + enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; + }; + + template struct enable_if {}; + template <> struct enable_if { + typedef empty result; + }; + + template + struct is_convertible : public enable_if::result > { + }; + } + +// ------------------------------ +// Small replacement for boost::shared_array, not threadsafe because no +// atomic reference counter is in use. +// ------------------------------ +template +class shared_array +{ + template friend class shared_array; + + template friend bool operator== (const shared_array& a, const shared_array& b); + template friend bool operator!= (const shared_array& a, const shared_array& b); + template friend bool operator< (const shared_array& a, const shared_array& b); + +public: + + typedef T element_type; + +public: + + // provide a default constructor + shared_array() + : ptr() + , ctr(NULL) + { + } + + // construction from an existing object of type T + explicit shared_array(T* ptr) + : ptr(ptr) + , ctr(ptr ? new array_detail::controller() : NULL) + { + } + + shared_array(const shared_array& r) + : ptr(r.ptr) + , ctr(r.ctr ? r.ctr->incref() : NULL) + { + } + + template + shared_array(const shared_array& r,typename detail::is_convertible::result = detail::empty()) + : ptr(r.ptr) + , ctr(r.ctr ? r.ctr->incref() : NULL) + { + } + + // automatic destruction of the wrapped object when all + // references are freed. + ~shared_array() { + if (ctr) { + ctr = ctr->decref(ptr); + } + } + + shared_array& operator=(const shared_array& r) { + if (this == &r) { + return *this; + } + if (ctr) { + ctr->decref(ptr); + } + ptr = r.ptr; + ctr = ptr?r.ctr->incref():NULL; + return *this; + } + + template + shared_array& operator=(const shared_array& r) { + if (this == &r) { + return *this; + } + if (ctr) { + ctr->decref(ptr); + } + ptr = r.ptr; + ctr = ptr?r.ctr->incref():NULL; + return *this; + } + + // pointer access + inline operator T*() { + return ptr; + } + + inline T* operator-> () const { + return ptr; + } + + // standard semantics + inline T* get() { + return ptr; + } + + T& operator[] (std::ptrdiff_t index) const { + return ptr[index]; + } + + inline const T* get() const { + return ptr; + } + + inline operator bool () const { + return ptr != NULL; + } + + inline bool unique() const { + return use_count() == 1; + } + + inline long use_count() const { + return ctr->get(); + } + + inline void reset (T* t = 0) { + if (ctr) { + ctr->decref(ptr); + } + ptr = t; + ctr = ptr?new array_detail::controller():NULL; + } + + void swap(shared_array & b) { + std::swap(ptr, b.ptr); + std::swap(ctr, b.ctr); + } + + +private: + + // encapsulated object pointer + T* ptr; + + // control block + array_detail::controller* ctr; +}; + +template +inline void swap(shared_array & a, shared_array & b) +{ + a.swap(b); +} + +template +bool operator== (const shared_array& a, const shared_array& b) { + return a.ptr == b.ptr; +} +template +bool operator!= (const shared_array& a, const shared_array& b) { + return a.ptr != b.ptr; +} + +template +bool operator< (const shared_array& a, const shared_array& b) { + return a.ptr < b.ptr; +} + + +} // end of namespace boost + +#else +# error "shared_array.h was already included" +#endif +#endif // INCLUDED_AI_BOOST_SHARED_ARRAY diff --git a/code/BoostWorkaround/boost/shared_ptr.hpp b/code/BoostWorkaround/boost/shared_ptr.hpp index d3d91f3fe..732adcaff 100644 --- a/code/BoostWorkaround/boost/shared_ptr.hpp +++ b/code/BoostWorkaround/boost/shared_ptr.hpp @@ -1,260 +1,260 @@ - -#ifndef INCLUDED_AI_BOOST_SHARED_PTR -#define INCLUDED_AI_BOOST_SHARED_PTR - -#ifndef BOOST_SHARED_PTR_HPP_INCLUDED - -// ------------------------------ -// Internal stub - -#include //NULL -#include //std::swap -namespace boost { - namespace detail { - class controller { - public: - - controller() - : cnt(1) - {} - - public: - - template - controller* decref(T* pt) { - if (--cnt <= 0) { - delete this; - delete pt; - } - return NULL; - } - - controller* incref() { - ++cnt; - return this; - } - - long get() const { - return cnt; - } - - private: - long cnt; - }; - - struct empty {}; - - template - struct is_convertible_stub { - - struct yes {char s[1];}; - struct no {char s[2];}; - - static yes foo(DEST*); - static no foo(...); - - enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; - }; - - template struct enable_if {}; - template <> struct enable_if { - typedef empty result; - }; - - template - struct is_convertible : public enable_if::result > { - }; - } - -// ------------------------------ -// Small replacement for boost::shared_ptr, not threadsafe because no -// atomic reference counter is in use. -// ------------------------------ -template -class shared_ptr -{ - template friend class shared_ptr; - - template friend shared_ptr static_pointer_cast (shared_ptr ptr); - template friend shared_ptr dynamic_pointer_cast (shared_ptr ptr); - template friend shared_ptr const_pointer_cast (shared_ptr ptr); - - template friend bool operator== (const shared_ptr& a, const shared_ptr& b); - template friend bool operator!= (const shared_ptr& a, const shared_ptr& b); - template friend bool operator< (const shared_ptr& a, const shared_ptr& b); - -public: - - typedef T element_type; - -public: - - // provide a default constructor - shared_ptr() - : ptr() - , ctr(NULL) - { - } - - // construction from an existing object of type T - explicit shared_ptr(T* ptr) - : ptr(ptr) - , ctr(ptr ? new detail::controller() : NULL) - { - } - - shared_ptr(const shared_ptr& r) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - template - shared_ptr(const shared_ptr& r,typename detail::is_convertible::result = detail::empty()) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - // automatic destruction of the wrapped object when all - // references are freed. - ~shared_ptr() { - if (ctr) { - ctr = ctr->decref(ptr); - } - } - - shared_ptr& operator=(const shared_ptr& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - template - shared_ptr& operator=(const shared_ptr& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - // pointer access - inline operator T*() const { - return ptr; - } - - inline T* operator-> () const { - return ptr; - } - - // standard semantics - inline T* get() { - return ptr; - } - - inline const T* get() const { - return ptr; - } - - inline operator bool () const { - return ptr != NULL; - } - - inline bool unique() const { - return use_count() == 1; - } - - inline long use_count() const { - return ctr->get(); - } - - inline void reset (T* t = 0) { - if (ctr) { - ctr->decref(ptr); - } - ptr = t; - ctr = ptr?new detail::controller():NULL; - } - - void swap(shared_ptr & b) { - std::swap(ptr, b.ptr); - std::swap(ctr, b.ctr); - } - -private: - - - // for use by the various xxx_pointer_cast helper templates - explicit shared_ptr(T* ptr, detail::controller* ctr) - : ptr(ptr) - , ctr(ctr->incref()) - { - } - -private: - - // encapsulated object pointer - T* ptr; - - // control block - detail::controller* ctr; -}; - -template -inline void swap(shared_ptr & a, shared_ptr & b) -{ - a.swap(b); -} - -template -bool operator== (const shared_ptr& a, const shared_ptr& b) { - return a.ptr == b.ptr; -} -template -bool operator!= (const shared_ptr& a, const shared_ptr& b) { - return a.ptr != b.ptr; -} - -template -bool operator< (const shared_ptr& a, const shared_ptr& b) { - return a.ptr < b.ptr; -} - - -template -inline shared_ptr static_pointer_cast( shared_ptr ptr) -{ - return shared_ptr(static_cast(ptr.ptr),ptr.ctr); -} - -template -inline shared_ptr dynamic_pointer_cast( shared_ptr ptr) -{ - return shared_ptr(dynamic_cast(ptr.ptr),ptr.ctr); -} - -template -inline shared_ptr const_pointer_cast( shared_ptr ptr) -{ - return shared_ptr(const_cast(ptr.ptr),ptr.ctr); -} - - - -} // end of namespace boost - -#else -# error "shared_ptr.h was already included" -#endif -#endif // INCLUDED_AI_BOOST_SHARED_PTR + +#ifndef INCLUDED_AI_BOOST_SHARED_PTR +#define INCLUDED_AI_BOOST_SHARED_PTR + +#ifndef BOOST_SHARED_PTR_HPP_INCLUDED + +// ------------------------------ +// Internal stub + +#include //NULL +#include //std::swap +namespace boost { + namespace detail { + class controller { + public: + + controller() + : cnt(1) + {} + + public: + + template + controller* decref(T* pt) { + if (--cnt <= 0) { + delete this; + delete pt; + } + return NULL; + } + + controller* incref() { + ++cnt; + return this; + } + + long get() const { + return cnt; + } + + private: + long cnt; + }; + + struct empty {}; + + template + struct is_convertible_stub { + + struct yes {char s[1];}; + struct no {char s[2];}; + + static yes foo(DEST*); + static no foo(...); + + enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; + }; + + template struct enable_if {}; + template <> struct enable_if { + typedef empty result; + }; + + template + struct is_convertible : public enable_if::result > { + }; + } + +// ------------------------------ +// Small replacement for boost::shared_ptr, not threadsafe because no +// atomic reference counter is in use. +// ------------------------------ +template +class shared_ptr +{ + template friend class shared_ptr; + + template friend shared_ptr static_pointer_cast (shared_ptr ptr); + template friend shared_ptr dynamic_pointer_cast (shared_ptr ptr); + template friend shared_ptr const_pointer_cast (shared_ptr ptr); + + template friend bool operator== (const shared_ptr& a, const shared_ptr& b); + template friend bool operator!= (const shared_ptr& a, const shared_ptr& b); + template friend bool operator< (const shared_ptr& a, const shared_ptr& b); + +public: + + typedef T element_type; + +public: + + // provide a default constructor + shared_ptr() + : ptr() + , ctr(NULL) + { + } + + // construction from an existing object of type T + explicit shared_ptr(T* ptr) + : ptr(ptr) + , ctr(ptr ? new detail::controller() : NULL) + { + } + + shared_ptr(const shared_ptr& r) + : ptr(r.ptr) + , ctr(r.ctr ? r.ctr->incref() : NULL) + { + } + + template + shared_ptr(const shared_ptr& r,typename detail::is_convertible::result = detail::empty()) + : ptr(r.ptr) + , ctr(r.ctr ? r.ctr->incref() : NULL) + { + } + + // automatic destruction of the wrapped object when all + // references are freed. + ~shared_ptr() { + if (ctr) { + ctr = ctr->decref(ptr); + } + } + + shared_ptr& operator=(const shared_ptr& r) { + if (this == &r) { + return *this; + } + if (ctr) { + ctr->decref(ptr); + } + ptr = r.ptr; + ctr = ptr?r.ctr->incref():NULL; + return *this; + } + + template + shared_ptr& operator=(const shared_ptr& r) { + if (this == &r) { + return *this; + } + if (ctr) { + ctr->decref(ptr); + } + ptr = r.ptr; + ctr = ptr?r.ctr->incref():NULL; + return *this; + } + + // pointer access + inline operator T*() const { + return ptr; + } + + inline T* operator-> () const { + return ptr; + } + + // standard semantics + inline T* get() { + return ptr; + } + + inline const T* get() const { + return ptr; + } + + inline operator bool () const { + return ptr != NULL; + } + + inline bool unique() const { + return use_count() == 1; + } + + inline long use_count() const { + return ctr->get(); + } + + inline void reset (T* t = 0) { + if (ctr) { + ctr->decref(ptr); + } + ptr = t; + ctr = ptr?new detail::controller():NULL; + } + + void swap(shared_ptr & b) { + std::swap(ptr, b.ptr); + std::swap(ctr, b.ctr); + } + +private: + + + // for use by the various xxx_pointer_cast helper templates + explicit shared_ptr(T* ptr, detail::controller* ctr) + : ptr(ptr) + , ctr(ctr->incref()) + { + } + +private: + + // encapsulated object pointer + T* ptr; + + // control block + detail::controller* ctr; +}; + +template +inline void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +template +bool operator== (const shared_ptr& a, const shared_ptr& b) { + return a.ptr == b.ptr; +} +template +bool operator!= (const shared_ptr& a, const shared_ptr& b) { + return a.ptr != b.ptr; +} + +template +bool operator< (const shared_ptr& a, const shared_ptr& b) { + return a.ptr < b.ptr; +} + + +template +inline shared_ptr static_pointer_cast( shared_ptr ptr) +{ + return shared_ptr(static_cast(ptr.ptr),ptr.ctr); +} + +template +inline shared_ptr dynamic_pointer_cast( shared_ptr ptr) +{ + return shared_ptr(dynamic_cast(ptr.ptr),ptr.ctr); +} + +template +inline shared_ptr const_pointer_cast( shared_ptr ptr) +{ + return shared_ptr(const_cast(ptr.ptr),ptr.ctr); +} + + + +} // end of namespace boost + +#else +# error "shared_ptr.h was already included" +#endif +#endif // INCLUDED_AI_BOOST_SHARED_PTR diff --git a/code/BoostWorkaround/boost/static_assert.hpp b/code/BoostWorkaround/boost/static_assert.hpp index 718157622..a533c6fa9 100644 --- a/code/BoostWorkaround/boost/static_assert.hpp +++ b/code/BoostWorkaround/boost/static_assert.hpp @@ -1,20 +1,20 @@ - -#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED -#define AI_BOOST_STATIC_ASSERT_INCLUDED - -#ifndef BOOST_STATIC_ASSERT - -namespace boost { - namespace detail { - - template class static_assertion_failure; - template <> class static_assertion_failure {}; - } -} - - -#define BOOST_STATIC_ASSERT(eval) \ -{boost::detail::static_assertion_failure<(eval)> assert_dummy;(void)assert_dummy;} - -#endif -#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED + +#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED +#define AI_BOOST_STATIC_ASSERT_INCLUDED + +#ifndef BOOST_STATIC_ASSERT + +namespace boost { + namespace detail { + + template class static_assertion_failure; + template <> class static_assertion_failure {}; + } +} + + +#define BOOST_STATIC_ASSERT(eval) \ +{boost::detail::static_assertion_failure<(eval)> assert_dummy;(void)assert_dummy;} + +#endif +#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED diff --git a/code/BoostWorkaround/boost/timer.hpp b/code/BoostWorkaround/boost/timer.hpp index edc32378e..b22e4c401 100644 --- a/code/BoostWorkaround/boost/timer.hpp +++ b/code/BoostWorkaround/boost/timer.hpp @@ -1,73 +1,73 @@ -// boost timer.hpp header file ---------------------------------------------// - -// Copyright Beman Dawes 1994-99. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/timer for documentation. - -// Revision History -// 01 Apr 01 Modified to use new header. (JMaddock) -// 12 Jan 01 Change to inline implementation to allow use without library -// builds. See docs for more rationale. (Beman Dawes) -// 25 Sep 99 elapsed_max() and elapsed_min() added (John Maddock) -// 16 Jul 99 Second beta -// 6 Jul 99 Initial boost version - -#ifndef BOOST_TIMER_HPP -#define BOOST_TIMER_HPP - -//#include -#include -#include -//#include - -# ifdef BOOST_NO_STDC_NAMESPACE - namespace std { using ::clock_t; using ::clock; } -# endif - - -namespace boost { - -// timer -------------------------------------------------------------------// - -// A timer object measures elapsed time. - -// It is recommended that implementations measure wall clock rather than CPU -// time since the intended use is performance measurement on systems where -// total elapsed time is more important than just process or CPU time. - -// Warnings: The maximum measurable elapsed time may well be only 596.5+ hours -// due to implementation limitations. The accuracy of timings depends on the -// accuracy of timing information provided by the underlying platform, and -// this varies a great deal from platform to platform. - -class timer -{ - public: - timer() { _start_time = std::clock(); } // postcondition: elapsed()==0 -// timer( const timer& src ); // post: elapsed()==src.elapsed() -// ~timer(){} -// timer& operator=( const timer& src ); // post: elapsed()==src.elapsed() - void restart() { _start_time = std::clock(); } // post: elapsed()==0 - double elapsed() const // return elapsed time in seconds - { return double(std::clock() - _start_time) / CLOCKS_PER_SEC; } - - double elapsed_max() const // return estimated maximum value for elapsed() - // Portability warning: elapsed_max() may return too high a value on systems - // where std::clock_t overflows or resets at surprising values. - { - return (double((std::numeric_limits::max)()) - - double(_start_time)) / double(CLOCKS_PER_SEC); - } - - double elapsed_min() const // return minimum value for elapsed() - { return double(1)/double(CLOCKS_PER_SEC); } - - private: - std::clock_t _start_time; -}; // timer - -} // namespace boost - -#endif // BOOST_TIMER_HPP +// boost timer.hpp header file ---------------------------------------------// + +// Copyright Beman Dawes 1994-99. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/timer for documentation. + +// Revision History +// 01 Apr 01 Modified to use new header. (JMaddock) +// 12 Jan 01 Change to inline implementation to allow use without library +// builds. See docs for more rationale. (Beman Dawes) +// 25 Sep 99 elapsed_max() and elapsed_min() added (John Maddock) +// 16 Jul 99 Second beta +// 6 Jul 99 Initial boost version + +#ifndef BOOST_TIMER_HPP +#define BOOST_TIMER_HPP + +//#include +#include +#include +//#include + +# ifdef BOOST_NO_STDC_NAMESPACE + namespace std { using ::clock_t; using ::clock; } +# endif + + +namespace boost { + +// timer -------------------------------------------------------------------// + +// A timer object measures elapsed time. + +// It is recommended that implementations measure wall clock rather than CPU +// time since the intended use is performance measurement on systems where +// total elapsed time is more important than just process or CPU time. + +// Warnings: The maximum measurable elapsed time may well be only 596.5+ hours +// due to implementation limitations. The accuracy of timings depends on the +// accuracy of timing information provided by the underlying platform, and +// this varies a great deal from platform to platform. + +class timer +{ + public: + timer() { _start_time = std::clock(); } // postcondition: elapsed()==0 +// timer( const timer& src ); // post: elapsed()==src.elapsed() +// ~timer(){} +// timer& operator=( const timer& src ); // post: elapsed()==src.elapsed() + void restart() { _start_time = std::clock(); } // post: elapsed()==0 + double elapsed() const // return elapsed time in seconds + { return double(std::clock() - _start_time) / CLOCKS_PER_SEC; } + + double elapsed_max() const // return estimated maximum value for elapsed() + // Portability warning: elapsed_max() may return too high a value on systems + // where std::clock_t overflows or resets at surprising values. + { + return (double((std::numeric_limits::max)()) + - double(_start_time)) / double(CLOCKS_PER_SEC); + } + + double elapsed_min() const // return minimum value for elapsed() + { return double(1)/double(CLOCKS_PER_SEC); } + + private: + std::clock_t _start_time; +}; // timer + +} // namespace boost + +#endif // BOOST_TIMER_HPP diff --git a/code/BoostWorkaround/boost/tuple/tuple.hpp b/code/BoostWorkaround/boost/tuple/tuple.hpp index ed5d11861..d196f297d 100644 --- a/code/BoostWorkaround/boost/tuple/tuple.hpp +++ b/code/BoostWorkaround/boost/tuple/tuple.hpp @@ -1,283 +1,283 @@ -// A very small replacement for boost::tuple -// (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net] - -#ifndef BOOST_TUPLE_INCLUDED -#define BOOST_TUPLE_INCLUDED - -namespace boost { - namespace detail { - - // Represents an empty tuple slot (up to 5 supported) - struct nulltype {}; - - // For readable error messages - struct tuple_component_idx_out_of_bounds; - - // To share some code for the const/nonconst versions of the getters - template - struct ConstIf { - typedef T t; - }; - - template - struct ConstIf { - typedef const T t; - }; - - // Predeclare some stuff - template struct value_getter; - - // Helper to obtain the type of a tuple element - template - struct type_getter { - typedef type_getter next_elem_getter; - typedef typename next_elem_getter::type type; - }; - - template - struct type_getter { - typedef T type; - }; - - // Base class for all explicit specializations of list_elem - template - struct list_elem_base { - - // Store template parameters - typedef TNEXT next_type; - typedef T type; - - static const unsigned nidx = NIDX; - }; - - // Represents an element in the tuple component list - template - struct list_elem : list_elem_base{ - - // Real members - T me; - TNEXT next; - - // Get the value of a specific tuple element - template - typename type_getter::type& get () { - value_getter s; - return s(*this); - } - - // Get the value of a specific tuple element - template - const typename type_getter::type& get () const { - value_getter s; - return s(*this); - } - - // Explicit cast - template - operator list_elem () const { - list_elem ret; - ret.me = (T2)me; - ret.next = next; - return ret; - } - - // Recursively compare two elements (last element returns always true) - bool operator == (const list_elem& s) const { - return (me == s.me && next == s.next); - } - }; - - // Represents a non-used tuple element - the very last element processed - template - struct list_elem : list_elem_base { - template struct value_getter { - /* just dummy members to produce readable error messages */ - tuple_component_idx_out_of_bounds operator () (typename ConstIf::t& me); - }; - template struct type_getter { - /* just dummy members to produce readable error messages */ - typedef tuple_component_idx_out_of_bounds type; - }; - - // dummy - list_elem& operator = (const list_elem& /*other*/) { - return *this; - } - - // dummy - bool operator == (const list_elem& other) { - return true; - } - }; - - // Represents the absolute end of the list - typedef list_elem list_end; - - // Helper obtain to query the value of a tuple element - // NOTE: This can't be a nested class as the compiler won't accept a full or - // partial specialization of a nested class of a non-specialized template - template - struct value_getter { - - // calling list_elem - typedef list_elem outer_elem; - - // typedef for the getter for next element - typedef value_getter next_value_getter; - - typename ConstIf::type>::t& - operator () (typename ConstIf::t& me) { - - next_value_getter s; - return s(me.next); - } - }; - - template - struct value_getter { - typedef list_elem outer_elem; - - typename ConstIf::t& operator () (typename ConstIf::t& me) { - return me.me; - } - }; - } - - // A very minimal implementation for up to 5 elements - template - class tuple { - - template - friend class tuple; - - private: - - typedef detail::list_elem > > > > very_long; - - very_long m; - - public: - - // Get a specific tuple element - template - typename detail::type_getter::type& get () { - return m.template get(); - } - - // ... and the const version - template - const typename detail::type_getter::type& get () const { - return m.template get(); - } - - - // comparison operators - bool operator== (const tuple& other) const { - return m == other.m; - } - - // ... and the other way round - bool operator!= (const tuple& other) const { - return !(m == other.m); - } - - // cast to another tuple - all single elements must be convertible - template - operator tuple () const { - tuple s; - s.m = (typename tuple ::very_long)m; - return s; - } - }; - - // Another way to access an element ... - template - inline typename tuple::very_long::template type_getter::type& get ( - tuple& m) { - return m.template get(); - } - - // ... and the const version - template - inline const typename tuple::very_long::template type_getter::type& get ( - const tuple& m) { - return m.template get(); - } - - // Constructs a tuple with 5 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1,const T2& t2,const T3& t3,const T4& t4) { - - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - t.template get<2>() = t2; - t.template get<3>() = t3; - t.template get<4>() = t4; - return t; - } - - // Constructs a tuple with 4 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1,const T2& t2,const T3& t3) { - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - t.template get<2>() = t2; - t.template get<3>() = t3; - return t; - } - - // Constructs a tuple with 3 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1,const T2& t2) { - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - t.template get<2>() = t2; - return t; - } - - // Constructs a tuple with 2 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1) { - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - return t; - } - - // Constructs a tuple with 1 elements (well ...) - template - inline tuple make_tuple (const T0& t0) { - tuple t; - t.template get<0>() = t0; - return t; - } - - // Constructs a tuple with 0 elements (well ...) - inline tuple <> make_tuple () { - tuple <> t; - return t; - } -} - -#endif // !! BOOST_TUPLE_INCLUDED +// A very small replacement for boost::tuple +// (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net] + +#ifndef BOOST_TUPLE_INCLUDED +#define BOOST_TUPLE_INCLUDED + +namespace boost { + namespace detail { + + // Represents an empty tuple slot (up to 5 supported) + struct nulltype {}; + + // For readable error messages + struct tuple_component_idx_out_of_bounds; + + // To share some code for the const/nonconst versions of the getters + template + struct ConstIf { + typedef T t; + }; + + template + struct ConstIf { + typedef const T t; + }; + + // Predeclare some stuff + template struct value_getter; + + // Helper to obtain the type of a tuple element + template + struct type_getter { + typedef type_getter next_elem_getter; + typedef typename next_elem_getter::type type; + }; + + template + struct type_getter { + typedef T type; + }; + + // Base class for all explicit specializations of list_elem + template + struct list_elem_base { + + // Store template parameters + typedef TNEXT next_type; + typedef T type; + + static const unsigned nidx = NIDX; + }; + + // Represents an element in the tuple component list + template + struct list_elem : list_elem_base{ + + // Real members + T me; + TNEXT next; + + // Get the value of a specific tuple element + template + typename type_getter::type& get () { + value_getter s; + return s(*this); + } + + // Get the value of a specific tuple element + template + const typename type_getter::type& get () const { + value_getter s; + return s(*this); + } + + // Explicit cast + template + operator list_elem () const { + list_elem ret; + ret.me = (T2)me; + ret.next = next; + return ret; + } + + // Recursively compare two elements (last element returns always true) + bool operator == (const list_elem& s) const { + return (me == s.me && next == s.next); + } + }; + + // Represents a non-used tuple element - the very last element processed + template + struct list_elem : list_elem_base { + template struct value_getter { + /* just dummy members to produce readable error messages */ + tuple_component_idx_out_of_bounds operator () (typename ConstIf::t& me); + }; + template struct type_getter { + /* just dummy members to produce readable error messages */ + typedef tuple_component_idx_out_of_bounds type; + }; + + // dummy + list_elem& operator = (const list_elem& /*other*/) { + return *this; + } + + // dummy + bool operator == (const list_elem& other) { + return true; + } + }; + + // Represents the absolute end of the list + typedef list_elem list_end; + + // Helper obtain to query the value of a tuple element + // NOTE: This can't be a nested class as the compiler won't accept a full or + // partial specialization of a nested class of a non-specialized template + template + struct value_getter { + + // calling list_elem + typedef list_elem outer_elem; + + // typedef for the getter for next element + typedef value_getter next_value_getter; + + typename ConstIf::type>::t& + operator () (typename ConstIf::t& me) { + + next_value_getter s; + return s(me.next); + } + }; + + template + struct value_getter { + typedef list_elem outer_elem; + + typename ConstIf::t& operator () (typename ConstIf::t& me) { + return me.me; + } + }; + } + + // A very minimal implementation for up to 5 elements + template + class tuple { + + template + friend class tuple; + + private: + + typedef detail::list_elem > > > > very_long; + + very_long m; + + public: + + // Get a specific tuple element + template + typename detail::type_getter::type& get () { + return m.template get(); + } + + // ... and the const version + template + const typename detail::type_getter::type& get () const { + return m.template get(); + } + + + // comparison operators + bool operator== (const tuple& other) const { + return m == other.m; + } + + // ... and the other way round + bool operator!= (const tuple& other) const { + return !(m == other.m); + } + + // cast to another tuple - all single elements must be convertible + template + operator tuple () const { + tuple s; + s.m = (typename tuple ::very_long)m; + return s; + } + }; + + // Another way to access an element ... + template + inline typename tuple::very_long::template type_getter::type& get ( + tuple& m) { + return m.template get(); + } + + // ... and the const version + template + inline const typename tuple::very_long::template type_getter::type& get ( + const tuple& m) { + return m.template get(); + } + + // Constructs a tuple with 5 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1,const T2& t2,const T3& t3,const T4& t4) { + + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + t.template get<2>() = t2; + t.template get<3>() = t3; + t.template get<4>() = t4; + return t; + } + + // Constructs a tuple with 4 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1,const T2& t2,const T3& t3) { + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + t.template get<2>() = t2; + t.template get<3>() = t3; + return t; + } + + // Constructs a tuple with 3 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1,const T2& t2) { + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + t.template get<2>() = t2; + return t; + } + + // Constructs a tuple with 2 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1) { + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + return t; + } + + // Constructs a tuple with 1 elements (well ...) + template + inline tuple make_tuple (const T0& t0) { + tuple t; + t.template get<0>() = t0; + return t; + } + + // Constructs a tuple with 0 elements (well ...) + inline tuple <> make_tuple () { + tuple <> t; + return t; + } +} + +#endif // !! BOOST_TUPLE_INCLUDED diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index d223f8184..cdc3cedeb 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER #include +#include #include "ColladaParser.h" #include "fast_atof.h" #include "ParsingUtils.h" @@ -1066,6 +1067,12 @@ void ColladaParser::ReadLight( Collada::Light& pLight) pLight.mFalloffAngle = ReadFloatFromTextContent(); TestClosing("hotspot_beam"); } + // OpenCOLLADA extensions + // ------------------------------------------------------- + else if (IsElement("decay_falloff")) { + pLight.mOuterAngle = ReadFloatFromTextContent(); + TestClosing("decay_falloff"); + } } else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if( strcmp( mReader->getNodeName(), "light") == 0) @@ -1998,7 +2005,8 @@ void ColladaParser::ReadIndexData( Mesh* pMesh) } #ifdef ASSIMP_BUILD_DEBUG - if (primType != Prim_TriFans && primType != Prim_TriStrips) { + if (primType != Prim_TriFans && primType != Prim_TriStrips && + primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'. ai_assert(actualPrimitives == numPrimitives); } #endif @@ -2107,13 +2115,19 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP } } - // complain if the index count doesn't fit - if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets) - ThrowException( "Expected different index count in

element."); - else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0) - ThrowException( "Expected different index count in

element."); + // complain if the index count doesn't fit + if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets) { + if (pPrimType == Prim_Lines) { + // HACK: We just fix this number since SketchUp 15.3.331 writes the wrong 'count' for 'lines' + ReportWarning( "Expected different index count in

element, %d instead of %d.", indices.size(), expectedPointCount * numOffsets); + pNumPrimitives = (indices.size() / numOffsets) / 2; + } else + ThrowException( "Expected different index count in

element."); - // find the data for all sources + } else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0) + ThrowException( "Expected different index count in

element."); + + // find the data for all sources for( std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) { InputChannel& input = *it; @@ -2712,6 +2726,21 @@ AI_WONT_RETURN void ColladaParser::ThrowException( const std::string& pError) co { throw DeadlyImportError( boost::str( boost::format( "Collada: %s - %s") % mFileName % pError)); } +void ColladaParser::ReportWarning(const char* msg,...) +{ + ai_assert(NULL != msg); + + va_list args; + va_start(args,msg); + + char szBuffer[3000]; + const int iLen = vsprintf(szBuffer,msg,args); + ai_assert(iLen > 0); + + va_end(args); + DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen)); +} + // ------------------------------------------------------------------------------------------------ // Skips all data until the end node of the current element diff --git a/code/ColladaParser.h b/code/ColladaParser.h index 09edc4fce..a945b70a7 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -1,42 +1,42 @@ /* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2015, 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. - ----------------------------------------------------------------------- -*/ + Open Asset Import Library (assimp) + ---------------------------------------------------------------------- + + Copyright (c) 2006-2015, assimp team + All rights reserved. + + Redistribution and use of this software in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + * Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ---------------------------------------------------------------------- + */ /** @file ColladaParser.h * @brief Defines the parser helper class for the collada loader @@ -52,301 +52,302 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { - -// ------------------------------------------------------------------------------------------ -/** Parser helper class for the Collada loader. - * - * Does all the XML reading and builds internal data structures from it, - * but leaves the resolving of all the references to the loader. -*/ -class ColladaParser -{ - friend class ColladaLoader; - -protected: - /** Constructor from XML file */ - ColladaParser( IOSystem* pIOHandler, const std::string& pFile); - - /** Destructor */ - ~ColladaParser(); - - /** Reads the contents of the file */ - void ReadContents(); - - /** Reads the structure of the file */ - void ReadStructure(); - - /** Reads asset informations such as coordinate system informations and legal blah */ - void ReadAssetInfo(); - - /** Reads the animation library */ - void ReadAnimationLibrary(); - - /** Reads an animation into the given parent structure */ - void ReadAnimation( Collada::Animation* pParent); - - /** Reads an animation sampler into the given anim channel */ - void ReadAnimationSampler( Collada::AnimationChannel& pChannel); - - /** Reads the skeleton controller library */ - void ReadControllerLibrary(); - - /** Reads a controller into the given mesh structure */ - void ReadController( Collada::Controller& pController); - - /** Reads the joint definitions for the given controller */ - void ReadControllerJoints( Collada::Controller& pController); - - /** Reads the joint weights for the given controller */ - void ReadControllerWeights( Collada::Controller& pController); - - /** Reads the image library contents */ - void ReadImageLibrary(); - - /** Reads an image entry into the given image */ - void ReadImage( Collada::Image& pImage); - - /** Reads the material library */ - void ReadMaterialLibrary(); - - /** Reads a material entry into the given material */ - void ReadMaterial( Collada::Material& pMaterial); - - /** Reads the camera library */ - void ReadCameraLibrary(); - - /** Reads a camera entry into the given camera */ - void ReadCamera( Collada::Camera& pCamera); - - /** Reads the light library */ - void ReadLightLibrary(); - - /** Reads a light entry into the given light */ - void ReadLight( Collada::Light& pLight); - - /** Reads the effect library */ - void ReadEffectLibrary(); - - /** Reads an effect entry into the given effect*/ - void ReadEffect( Collada::Effect& pEffect); - - /** Reads an COMMON effect profile */ - void ReadEffectProfileCommon( Collada::Effect& pEffect); - - /** Read sampler properties */ - void ReadSamplerProperties( Collada::Sampler& pSampler); - - /** Reads an effect entry containing a color or a texture defining that color */ - void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); - - /** Reads an effect entry containing a float */ - void ReadEffectFloat( float& pFloat); - - /** Reads an effect parameter specification of any kind */ - void ReadEffectParam( Collada::EffectParam& pParam); - - /** Reads the geometry library contents */ - void ReadGeometryLibrary(); - - /** Reads a geometry from the geometry library. */ - void ReadGeometry( Collada::Mesh* pMesh); - - /** Reads a mesh from the geometry library */ - void ReadMesh( Collada::Mesh* pMesh); - - /** Reads a source element - a combination of raw data and an accessor defining - * things that should not be redefinable. Yes, that's another rant. + + // ------------------------------------------------------------------------------------------ + /** Parser helper class for the Collada loader. + * + * Does all the XML reading and builds internal data structures from it, + * but leaves the resolving of all the references to the loader. */ - void ReadSource(); - - /** Reads a data array holding a number of elements, and stores it in the global library. - * Currently supported are array of floats and arrays of strings. - */ - void ReadDataArray(); - - /** Reads an accessor and stores it in the global library under the given ID - - * accessors use the ID of the parent element - */ - void ReadAccessor( const std::string& pID); - - /** Reads input declarations of per-vertex mesh data into the given mesh */ - void ReadVertexData( Collada::Mesh* pMesh); - - /** Reads input declarations of per-index mesh data into the given mesh */ - void ReadIndexData( Collada::Mesh* pMesh); - - /** Reads a single input channel element and stores it in the given array, if valid */ - void ReadInputChannel( std::vector& poChannels); - - /** Reads a

primitive index list and assembles the mesh data into the given mesh */ - size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector& pPerIndexChannels, - size_t pNumPrimitives, const std::vector& pVCount, Collada::PrimitiveType pPrimType); - - /** Copies the data for a single primitive into the mesh, based on the InputChannels */ - void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, - Collada::Mesh* pMesh, std::vector& pPerIndexChannels, - size_t currentPrimitive, const std::vector& indices); - - /** Reads one triangle of a tristrip into the mesh */ - void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, - std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); - - /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ - void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); - - /** Reads the library of node hierarchies and scene parts */ - void ReadSceneLibrary(); - - /** Reads a scene node's contents including children and stores it in the given node */ - void ReadSceneNode( Collada::Node* pNode); - - /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ - void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType); - - /** Reads a mesh reference in a node and adds it to the node's mesh list */ - void ReadNodeGeometry( Collada::Node* pNode); - - /** Reads the collada scene */ - void ReadScene(); - - // Processes bind_vertex_input and bind elements - void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); - -protected: - /** Aborts the file reading with an exception */ - AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX; - - /** Skips all data until the end node of the current element */ - void SkipElement(); - - /** Skips all data until the end node of the given element */ - void SkipElement( const char* pElement); - - /** Compares the current xml element name to the given string and returns true if equal */ - bool IsElement( const char* pName) const; - - /** Tests for the opening tag of the given element, throws an exception if not found */ - void TestOpening( const char* pName); - - /** Tests for the closing tag of the given element, throws an exception if not found */ - void TestClosing( const char* pName); - - /** Checks the present element for the presence of the attribute, returns its index - or throws an exception if not found */ - int GetAttribute( const char* pAttr) const; - - /** Returns the index of the named attribute or -1 if not found. Does not throw, - therefore useful for optional attributes */ - int TestAttribute( const char* pAttr) const; - - /** Reads the text contents of an element, throws an exception if not given. - Skips leading whitespace. */ - const char* GetTextContent(); - - /** Reads the text contents of an element, returns NULL if not given. - Skips leading whitespace. */ - const char* TestTextContent(); - - /** Reads a single bool from current text content */ - bool ReadBoolFromTextContent(); - - /** Reads a single float from current text content */ - float ReadFloatFromTextContent(); - - /** Calculates the resulting transformation from all the given transform steps */ - aiMatrix4x4 CalculateResultTransform( const std::vector& pTransforms) const; - - /** Determines the input data type for the given semantic string */ - Collada::InputType GetTypeForSemantic( const std::string& pSemantic); - - /** Finds the item in the given library by its reference, throws if not found */ - template const Type& ResolveLibraryReference( - const std::map& pLibrary, const std::string& pURL) const; - -protected: - /** Filename, for a verbose error message */ - std::string mFileName; - - /** XML reader, member for everyday use */ - irr::io::IrrXMLReader* mReader; - - /** All data arrays found in the file by ID. Might be referred to by actually - everyone. Collada, you are a steaming pile of indirection. */ - typedef std::map DataLibrary; - DataLibrary mDataLibrary; - - /** Same for accessors which define how the data in a data array is accessed. */ - typedef std::map AccessorLibrary; - AccessorLibrary mAccessorLibrary; - - /** Mesh library: mesh by ID */ - typedef std::map MeshLibrary; - MeshLibrary mMeshLibrary; - - /** node library: root node of the hierarchy part by ID */ - typedef std::map NodeLibrary; - NodeLibrary mNodeLibrary; - - /** Image library: stores texture properties by ID */ - typedef std::map ImageLibrary; - ImageLibrary mImageLibrary; - - /** Effect library: surface attributes by ID */ - typedef std::map EffectLibrary; - EffectLibrary mEffectLibrary; - - /** Material library: surface material by ID */ - typedef std::map MaterialLibrary; - MaterialLibrary mMaterialLibrary; - - /** Light library: surface light by ID */ - typedef std::map LightLibrary; - LightLibrary mLightLibrary; - - /** Camera library: surface material by ID */ - typedef std::map CameraLibrary; - CameraLibrary mCameraLibrary; - - /** Controller library: joint controllers by ID */ - typedef std::map ControllerLibrary; - ControllerLibrary mControllerLibrary; - - /** Pointer to the root node. Don't delete, it just points to one of - the nodes in the node library. */ - Collada::Node* mRootNode; - - /** Root animation container */ - Collada::Animation mAnims; - - /** Size unit: how large compared to a meter */ - float mUnitSize; - - /** Which is the up vector */ - enum { UP_X, UP_Y, UP_Z } mUpDirection; - - /** Collada file format version */ - Collada::FormatVersion mFormat; -}; - -// ------------------------------------------------------------------------------------------------ -// Check for element match -inline bool ColladaParser::IsElement( const char* pName) const -{ - ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); - return ::strcmp( mReader->getNodeName(), pName) == 0; -} - -// ------------------------------------------------------------------------------------------------ -// Finds the item in the given library by its reference, throws if not found -template -const Type& ColladaParser::ResolveLibraryReference( const std::map& pLibrary, const std::string& pURL) const -{ - typename std::map::const_iterator it = pLibrary.find( pURL); - if( it == pLibrary.end()) - ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL)); - return it->second; -} + class ColladaParser + { + friend class ColladaLoader; + + protected: + /** Constructor from XML file */ + ColladaParser( IOSystem* pIOHandler, const std::string& pFile); + + /** Destructor */ + ~ColladaParser(); + + /** Reads the contents of the file */ + void ReadContents(); + + /** Reads the structure of the file */ + void ReadStructure(); + + /** Reads asset informations such as coordinate system informations and legal blah */ + void ReadAssetInfo(); + + /** Reads the animation library */ + void ReadAnimationLibrary(); + + /** Reads an animation into the given parent structure */ + void ReadAnimation( Collada::Animation* pParent); + + /** Reads an animation sampler into the given anim channel */ + void ReadAnimationSampler( Collada::AnimationChannel& pChannel); + + /** Reads the skeleton controller library */ + void ReadControllerLibrary(); + + /** Reads a controller into the given mesh structure */ + void ReadController( Collada::Controller& pController); + + /** Reads the joint definitions for the given controller */ + void ReadControllerJoints( Collada::Controller& pController); + + /** Reads the joint weights for the given controller */ + void ReadControllerWeights( Collada::Controller& pController); + + /** Reads the image library contents */ + void ReadImageLibrary(); + + /** Reads an image entry into the given image */ + void ReadImage( Collada::Image& pImage); + + /** Reads the material library */ + void ReadMaterialLibrary(); + + /** Reads a material entry into the given material */ + void ReadMaterial( Collada::Material& pMaterial); + + /** Reads the camera library */ + void ReadCameraLibrary(); + + /** Reads a camera entry into the given camera */ + void ReadCamera( Collada::Camera& pCamera); + + /** Reads the light library */ + void ReadLightLibrary(); + + /** Reads a light entry into the given light */ + void ReadLight( Collada::Light& pLight); + + /** Reads the effect library */ + void ReadEffectLibrary(); + + /** Reads an effect entry into the given effect*/ + void ReadEffect( Collada::Effect& pEffect); + + /** Reads an COMMON effect profile */ + void ReadEffectProfileCommon( Collada::Effect& pEffect); + + /** Read sampler properties */ + void ReadSamplerProperties( Collada::Sampler& pSampler); + + /** Reads an effect entry containing a color or a texture defining that color */ + void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); + + /** Reads an effect entry containing a float */ + void ReadEffectFloat( float& pFloat); + + /** Reads an effect parameter specification of any kind */ + void ReadEffectParam( Collada::EffectParam& pParam); + + /** Reads the geometry library contents */ + void ReadGeometryLibrary(); + + /** Reads a geometry from the geometry library. */ + void ReadGeometry( Collada::Mesh* pMesh); + + /** Reads a mesh from the geometry library */ + void ReadMesh( Collada::Mesh* pMesh); + + /** Reads a source element - a combination of raw data and an accessor defining + * things that should not be redefinable. Yes, that's another rant. + */ + void ReadSource(); + + /** Reads a data array holding a number of elements, and stores it in the global library. + * Currently supported are array of floats and arrays of strings. + */ + void ReadDataArray(); + + /** Reads an accessor and stores it in the global library under the given ID - + * accessors use the ID of the parent element + */ + void ReadAccessor( const std::string& pID); + + /** Reads input declarations of per-vertex mesh data into the given mesh */ + void ReadVertexData( Collada::Mesh* pMesh); + + /** Reads input declarations of per-index mesh data into the given mesh */ + void ReadIndexData( Collada::Mesh* pMesh); + + /** Reads a single input channel element and stores it in the given array, if valid */ + void ReadInputChannel( std::vector& poChannels); + + /** Reads a

primitive index list and assembles the mesh data into the given mesh */ + size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector& pPerIndexChannels, + size_t pNumPrimitives, const std::vector& pVCount, Collada::PrimitiveType pPrimType); + + /** Copies the data for a single primitive into the mesh, based on the InputChannels */ + void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, + Collada::Mesh* pMesh, std::vector& pPerIndexChannels, + size_t currentPrimitive, const std::vector& indices); + + /** Reads one triangle of a tristrip into the mesh */ + void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, + std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); + + /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ + void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); + + /** Reads the library of node hierarchies and scene parts */ + void ReadSceneLibrary(); + + /** Reads a scene node's contents including children and stores it in the given node */ + void ReadSceneNode( Collada::Node* pNode); + + /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ + void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType); + + /** Reads a mesh reference in a node and adds it to the node's mesh list */ + void ReadNodeGeometry( Collada::Node* pNode); + + /** Reads the collada scene */ + void ReadScene(); + + // Processes bind_vertex_input and bind elements + void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); + + protected: + /** Aborts the file reading with an exception */ + AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX; + void ReportWarning(const char* msg,...); + /** Skips all data until the end node of the current element */ + void SkipElement(); + + /** Skips all data until the end node of the given element */ + void SkipElement( const char* pElement); + + /** Compares the current xml element name to the given string and returns true if equal */ + bool IsElement( const char* pName) const; + + /** Tests for the opening tag of the given element, throws an exception if not found */ + void TestOpening( const char* pName); + + /** Tests for the closing tag of the given element, throws an exception if not found */ + void TestClosing( const char* pName); + + /** Checks the present element for the presence of the attribute, returns its index + or throws an exception if not found */ + int GetAttribute( const char* pAttr) const; + + /** Returns the index of the named attribute or -1 if not found. Does not throw, + therefore useful for optional attributes */ + int TestAttribute( const char* pAttr) const; + + /** Reads the text contents of an element, throws an exception if not given. + Skips leading whitespace. */ + const char* GetTextContent(); + + /** Reads the text contents of an element, returns NULL if not given. + Skips leading whitespace. */ + const char* TestTextContent(); + + /** Reads a single bool from current text content */ + bool ReadBoolFromTextContent(); + + /** Reads a single float from current text content */ + float ReadFloatFromTextContent(); + + /** Calculates the resulting transformation from all the given transform steps */ + aiMatrix4x4 CalculateResultTransform( const std::vector& pTransforms) const; + + /** Determines the input data type for the given semantic string */ + Collada::InputType GetTypeForSemantic( const std::string& pSemantic); + + /** Finds the item in the given library by its reference, throws if not found */ + template const Type& ResolveLibraryReference( + const std::map& pLibrary, const std::string& pURL) const; + + protected: + /** Filename, for a verbose error message */ + std::string mFileName; + + /** XML reader, member for everyday use */ + irr::io::IrrXMLReader* mReader; + + /** All data arrays found in the file by ID. Might be referred to by actually + everyone. Collada, you are a steaming pile of indirection. */ + typedef std::map DataLibrary; + DataLibrary mDataLibrary; + + /** Same for accessors which define how the data in a data array is accessed. */ + typedef std::map AccessorLibrary; + AccessorLibrary mAccessorLibrary; + + /** Mesh library: mesh by ID */ + typedef std::map MeshLibrary; + MeshLibrary mMeshLibrary; + + /** node library: root node of the hierarchy part by ID */ + typedef std::map NodeLibrary; + NodeLibrary mNodeLibrary; + + /** Image library: stores texture properties by ID */ + typedef std::map ImageLibrary; + ImageLibrary mImageLibrary; + + /** Effect library: surface attributes by ID */ + typedef std::map EffectLibrary; + EffectLibrary mEffectLibrary; + + /** Material library: surface material by ID */ + typedef std::map MaterialLibrary; + MaterialLibrary mMaterialLibrary; + + /** Light library: surface light by ID */ + typedef std::map LightLibrary; + LightLibrary mLightLibrary; + + /** Camera library: surface material by ID */ + typedef std::map CameraLibrary; + CameraLibrary mCameraLibrary; + + /** Controller library: joint controllers by ID */ + typedef std::map ControllerLibrary; + ControllerLibrary mControllerLibrary; + + /** Pointer to the root node. Don't delete, it just points to one of + the nodes in the node library. */ + Collada::Node* mRootNode; + + /** Root animation container */ + Collada::Animation mAnims; + + /** Size unit: how large compared to a meter */ + float mUnitSize; + + /** Which is the up vector */ + enum { UP_X, UP_Y, UP_Z } mUpDirection; + + /** Collada file format version */ + Collada::FormatVersion mFormat; + }; + + // ------------------------------------------------------------------------------------------------ + // Check for element match + inline bool ColladaParser::IsElement( const char* pName) const + { + ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); + return ::strcmp( mReader->getNodeName(), pName) == 0; + } + + // ------------------------------------------------------------------------------------------------ + // Finds the item in the given library by its reference, throws if not found + template + const Type& ColladaParser::ResolveLibraryReference( const std::map& pLibrary, const std::string& pURL) const + { + typename std::map::const_iterator it = pLibrary.find( pURL); + if( it == pLibrary.end()) + ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL)); + return it->second; + } + } // end of namespace Assimp #endif // AI_COLLADAPARSER_H_INC diff --git a/code/FixNormalsStep.cpp b/code/FixNormalsStep.cpp index 426e7fbeb..5fe139e4b 100644 --- a/code/FixNormalsStep.cpp +++ b/code/FixNormalsStep.cpp @@ -152,8 +152,8 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index) if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false; // now compare the volumes of the bounding boxes - if (std::fabs(fDelta0_x * fDelta1_yz) < - std::fabs(fDelta1_x * fDelta1_y * fDelta1_z)) + if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) < + std::fabs(fDelta1_x * fDelta1_yz)) { if (!DefaultLogger::isNullLogger()) { diff --git a/code/IFCOpenings.cpp b/code/IFCOpenings.cpp index db2187e49..d1dd9f50c 100644 --- a/code/IFCOpenings.cpp +++ b/code/IFCOpenings.cpp @@ -602,12 +602,12 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1, const IfcVector2& m0, const IfcVector2& m1, IfcVector2& out0, IfcVector2& out1) { - const IfcVector2& n0_to_n1 = n1 - n0; + const IfcVector2 n0_to_n1 = n1 - n0; - const IfcVector2& n0_to_m0 = m0 - n0; - const IfcVector2& n1_to_m1 = m1 - n1; + const IfcVector2 n0_to_m0 = m0 - n0; + const IfcVector2 n1_to_m1 = m1 - n1; - const IfcVector2& n0_to_m1 = m1 - n0; + const IfcVector2 n0_to_m1 = m1 - n0; const IfcFloat e = 1e-5f; const IfcFloat smalle = 1e-9f; @@ -927,7 +927,7 @@ size_t CloseWindows(ContourVector& contours, IfcFloat best = static_cast(1e10); IfcVector3 bestv; - const IfcVector3& world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f); + const IfcVector3 world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f); BOOST_FOREACH(const TempOpening* opening, refs) { BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) { @@ -1066,7 +1066,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector& out_contour, const TempMesh // Project all points into the new coordinate system, collect min/max verts on the way BOOST_FOREACH(const IfcVector3& x, in_verts) { - const IfcVector3& vv = m * x; + const IfcVector3 vv = m * x; // keep Z offset in the plane coordinate system. Ignoring precision issues // (which are present, of course), this should be the same value for // all polygon vertices (assuming the polygon is planar). @@ -1144,7 +1144,7 @@ bool GenerateOpenings(std::vector& openings, std::vector contour_flat; IfcVector3 nor; - const IfcMatrix4& m = ProjectOntoPlane(contour_flat, curmesh, ok, nor); + const IfcMatrix4 m = ProjectOntoPlane(contour_flat, curmesh, ok, nor); if(!ok) { return false; } @@ -1227,7 +1227,7 @@ bool GenerateOpenings(std::vector& openings, bool side_flag = true; if (!is_2d_source) { - const IfcVector3& face_nor = ((profile_verts[vi_total+2] - profile_verts[vi_total]) ^ + const IfcVector3 face_nor = ((profile_verts[vi_total+2] - profile_verts[vi_total]) ^ (profile_verts[vi_total+1] - profile_verts[vi_total])).Normalize(); const IfcFloat abs_dot_face_nor = std::abs(nor * face_nor); @@ -1242,7 +1242,7 @@ bool GenerateOpenings(std::vector& openings, for (unsigned int vi = 0, vend = profile_vertcnts[f]; vi < vend; ++vi, ++vi_total) { const IfcVector3& x = profile_verts[vi_total]; - const IfcVector3& v = m * x; + const IfcVector3 v = m * x; IfcVector2 vv(v.x, v.y); //if(check_intersection) { @@ -1322,7 +1322,7 @@ bool GenerateOpenings(std::vector& openings, MakeDisjunctWindowContours(other, temp_contour, poly); if(poly.size() == 1) { - const BoundingBox& newbb = GetBoundingBox(poly[0].outer); + const BoundingBox newbb = GetBoundingBox(poly[0].outer); if (!BoundingBoxesOverlapping(ibb, newbb )) { // Good guy bounding box bb = newbb ; @@ -1438,7 +1438,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: // working coordinate system. bool ok; IfcVector3 nor; - const IfcMatrix3& m = DerivePlaneCoordinateSpace(curmesh, ok, nor); + const IfcMatrix3 m = DerivePlaneCoordinateSpace(curmesh, ok, nor); if (!ok) { return false; } @@ -1686,13 +1686,13 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: continue; } - const std::vector& tris = cdt->GetTriangles(); + const std::vector tris = cdt->GetTriangles(); // Collect the triangles we just produced BOOST_FOREACH(p2t::Triangle* tri, tris) { for(int i = 0; i < 3; ++i) { - const IfcVector2& v = IfcVector2( + const IfcVector2 v = IfcVector2( static_cast( tri->GetPoint(i)->x ), static_cast( tri->GetPoint(i)->y ) ); diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index 5ec073507..8de88055b 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -954,6 +954,9 @@ inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int LWO::ReferrerList& refList = mCurLayer->mPointReferrers; unsigned int i; + if (idx >= base->abAssigned.size()) { + throw DeadlyImportError("Bad index"); + } base->abAssigned[idx] = true; for (i = 0; i < numRead;++i) { base->rawData[idx*base->dims+i]= data[i]; diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index f7fafefdd..3852a64a2 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -783,6 +783,13 @@ void MD3Importer::InternReadFile( const std::string& pFile, // Allocate output storage pScene->mNumMeshes = pcHeader->NUM_SURFACES; + if (pcHeader->NUM_SURFACES == 0) { + throw DeadlyImportError("MD3: No surfaces"); + } else if (pcHeader->NUM_SURFACES > AI_MAX_ALLOC(aiMesh)) { + // We allocate pointers but check against the size of aiMesh + // since those pointers will eventually have to point to real objects + throw DeadlyImportError("MD3: Too many surfaces, would run out of memory"); + } pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mNumMaterials = pcHeader->NUM_SURFACES; diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 60c92661b..c5b8d63c3 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -355,6 +355,9 @@ void MDLImporter::InternReadFile_Quake1( ) for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) { union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;}; + if (szCurrent + sizeof(MDL::Skin) > this->mBuffer + this->iFileSize) { + throw DeadlyImportError("[Quake 1 MDL] Unexpected EOF"); + } pcSkin = (BE_NCONST MDL::Skin*)szCurrent; AI_SWAP4( pcSkin->group ); diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 02232fcd1..7bf6154df 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -133,15 +133,16 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, TextFileToBuffer(file.get(),m_Buffer); // Get the model name - std::string strModelName; + std::string modelName, folderName; std::string::size_type pos = pFile.find_last_of( "\\/" ); - if ( pos != std::string::npos ) - { - strModelName = pFile.substr(pos+1, pFile.size() - pos - 1); - } - else - { - strModelName = pFile; + if ( pos != std::string::npos ) { + modelName = pFile.substr(pos+1, pFile.size() - pos - 1); + folderName = pFile.substr( 0, pos ); + if ( folderName.empty() ) { + pIOHandler->PushDirectory( folderName ); + } + } else { + modelName = pFile; } // process all '\' @@ -161,13 +162,18 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, } // parse the file into a temporary representation - ObjFileParser parser(m_Buffer, strModelName, pIOHandler); + ObjFileParser parser(m_Buffer, modelName, pIOHandler); // And create the proper return structures out of it CreateDataFromImport(parser.GetModel(), pScene); // Clean up allocated storage for the next import m_Buffer.clear(); + + // Pop directory stack + if ( pIOHandler->StackSize() > 0 ) { + pIOHandler->PopDirectory(); + } } // ------------------------------------------------------------------------------------------------ @@ -380,6 +386,11 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, // Copy vertices of this mesh instance pMesh->mNumVertices = numIndices; + if (pMesh->mNumVertices == 0) { + throw DeadlyImportError( "OBJ: no vertices" ); + } else if (pMesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) { + throw DeadlyImportError( "OBJ: Too many vertices, would run out of memory" ); + } pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ]; // Allocate buffer for normal vectors diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index b2194a747..027d99543 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -61,21 +61,21 @@ const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; // ------------------------------------------------------------------- // Constructor with loaded data and directories. -ObjFileParser::ObjFileParser(std::vector &Data,const std::string &strModelName, IOSystem *io ) : - m_DataIt(Data.begin()), - m_DataItEnd(Data.end()), +ObjFileParser::ObjFileParser(std::vector &data,const std::string &modelName, IOSystem *io ) : + m_DataIt(data.begin()), + m_DataItEnd(data.end()), m_pModel(NULL), m_uiLine(0), m_pIO( io ) { - std::fill_n(m_buffer,BUFFERSIZE,0); + std::fill_n(m_buffer,Buffersize,0); // Create the model instance to store all the data m_pModel = new ObjFile::Model(); - m_pModel->m_ModelName = strModelName; + m_pModel->m_ModelName = modelName; // create default material and store it - m_pModel->m_pDefaultMaterial = new ObjFile::Material(); + m_pModel->m_pDefaultMaterial = new ObjFile::Material; m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL ); m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL ); m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial; @@ -248,20 +248,20 @@ void ObjFileParser::getVector( std::vector &point3d_array ) { } float x, y, z; if( 2 == numComponents ) { - copyNextWord( m_buffer, BUFFERSIZE ); + copyNextWord( m_buffer, Buffersize ); x = ( float ) fast_atof( m_buffer ); - copyNextWord( m_buffer, BUFFERSIZE ); + copyNextWord( m_buffer, Buffersize ); y = ( float ) fast_atof( m_buffer ); z = 0.0; } else if( 3 == numComponents ) { - copyNextWord( m_buffer, BUFFERSIZE ); + copyNextWord( m_buffer, Buffersize ); x = ( float ) fast_atof( m_buffer ); - copyNextWord( m_buffer, BUFFERSIZE ); + copyNextWord( m_buffer, Buffersize ); y = ( float ) fast_atof( m_buffer ); - copyNextWord( m_buffer, BUFFERSIZE ); + copyNextWord( m_buffer, Buffersize ); z = ( float ) fast_atof( m_buffer ); } else { throw DeadlyImportError( "OBJ: Invalid number of components" ); @@ -274,13 +274,13 @@ void ObjFileParser::getVector( std::vector &point3d_array ) { // Get values for a new 3D vector instance void ObjFileParser::getVector3(std::vector &point3d_array) { float x, y, z; - copyNextWord(m_buffer, BUFFERSIZE); + copyNextWord(m_buffer, Buffersize); x = (float) fast_atof(m_buffer); - copyNextWord(m_buffer, BUFFERSIZE); + copyNextWord(m_buffer, Buffersize); y = (float) fast_atof(m_buffer); - copyNextWord( m_buffer, BUFFERSIZE ); + copyNextWord( m_buffer, Buffersize ); z = ( float ) fast_atof( m_buffer ); point3d_array.push_back( aiVector3D( x, y, z ) ); @@ -291,10 +291,10 @@ void ObjFileParser::getVector3(std::vector &point3d_array) { // Get values for a new 2D vector instance void ObjFileParser::getVector2( std::vector &point2d_array ) { float x, y; - copyNextWord(m_buffer, BUFFERSIZE); + copyNextWord(m_buffer, Buffersize); x = (float) fast_atof(m_buffer); - copyNextWord(m_buffer, BUFFERSIZE); + copyNextWord(m_buffer, Buffersize); y = (float) fast_atof(m_buffer); point2d_array.push_back(aiVector2D(x, y)); @@ -306,12 +306,12 @@ void ObjFileParser::getVector2( std::vector &point2d_array ) { // Get values for a new face instance void ObjFileParser::getFace(aiPrimitiveType type) { - copyNextLine(m_buffer, BUFFERSIZE); + copyNextLine(m_buffer, Buffersize); if (m_DataIt == m_DataItEnd) return; char *pPtr = m_buffer; - char *pEnd = &pPtr[BUFFERSIZE]; + char *pEnd = &pPtr[Buffersize]; pPtr = getNextToken(pPtr, pEnd); if (pPtr == pEnd || *pPtr == '\0') return; @@ -468,8 +468,9 @@ void ObjFileParser::getMaterialDesc() // Get next data for material data m_DataIt = getNextToken(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) + if (m_DataIt == m_DataItEnd) { return; + } char *pStart = &(*m_DataIt); while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) { @@ -483,14 +484,11 @@ void ObjFileParser::getMaterialDesc() // Search for material std::map::iterator it = m_pModel->m_MaterialMap.find( strName ); - if ( it == m_pModel->m_MaterialMap.end() ) - { + if ( it == m_pModel->m_MaterialMap.end() ) { // Not found, use default material m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping"); - } - else - { + } else { // Found, using detected material m_pModel->m_pCurrentMaterial = (*it).second; if ( needsNewMesh( strName )) @@ -539,18 +537,24 @@ void ObjFileParser::getMaterialLib() // Check for existence const std::string strMatName(pStart, &(*m_DataIt)); - IOStream *pFile = m_pIO->Open(strMatName); + std::string absName; + if ( m_pIO->StackSize() > 0 ) { + const std::string &path = m_pIO->CurrentDirectory(); + absName = path + strMatName; + } else { + absName = strMatName; + } + IOStream *pFile = m_pIO->Open( absName ); - if (!pFile ) - { - DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); + if (!pFile ) { + DefaultLogger::get()->error( "OBJ: Unable to locate material file " + strMatName ); m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); return; } // Import material library data from file std::vector buffer; - BaseImporter::TextFileToBuffer(pFile,buffer); + BaseImporter::TextFileToBuffer( pFile, buffer ); m_pIO->Close( pFile ); // Importing the material library diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index 85f555567..66f378f29 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -62,10 +62,9 @@ class IOSystem; /// \class ObjFileParser /// \brief Parser for a obj waveform file -class ObjFileParser -{ +class ObjFileParser { public: - static const size_t BUFFERSIZE = 4096; + static const size_t Buffersize = 4096; typedef std::vector DataArray; typedef std::vector::iterator DataArrayIt; typedef std::vector::const_iterator ConstDataArrayIt; @@ -137,9 +136,10 @@ private: //! Current line (for debugging) unsigned int m_uiLine; //! Helper buffer - char m_buffer[BUFFERSIZE]; + char m_buffer[Buffersize]; /// Pointer to IO system instance. IOSystem *m_pIO; + /// Path to the current model }; } // Namespace Assimp diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 137a8c1e5..f260cc772 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -63,23 +63,23 @@ static const aiImporterDesc desc = { }; namespace Grammar { - static const char *MetricType = "Metric"; - static const char *Metric_DistanceType = "distance"; - static const char *Metric_AngleType = "angle"; - static const char *Metric_TimeType = "time"; - static const char *Metric_UpType = "up"; - static const char *NameType = "Name"; - static const char *ObjectRefType = "ObjectRef"; - static const char *MaterialRefType = "MaterialRef"; - static const char *MetricKeyType = "key"; - static const char *GeometryNodeType = "GeometryNode"; - static const char *GeometryObjectType = "GeometryObject"; - static const char *TransformType = "Transform"; - static const char *MeshType = "Mesh"; - static const char *VertexArrayType = "VertexArray"; - static const char *IndexArrayType = "IndexArray"; - static const char *MaterialType = "Material"; - static const char *ColorType = "Color"; + static const std::string MetricType = "Metric"; + static const std::string Metric_DistanceType = "distance"; + static const std::string Metric_AngleType = "angle"; + static const std::string Metric_TimeType = "time"; + static const std::string Metric_UpType = "up"; + static const std::string NameType = "Name"; + static const std::string ObjectRefType = "ObjectRef"; + static const std::string MaterialRefType = "MaterialRef"; + static const std::string MetricKeyType = "key"; + static const std::string GeometryNodeType = "GeometryNode"; + static const std::string GeometryObjectType = "GeometryObject"; + static const std::string TransformType = "Transform"; + static const std::string MeshType = "Mesh"; + static const std::string VertexArrayType = "VertexArray"; + static const std::string IndexArrayType = "IndexArray"; + static const std::string MaterialType = "Material"; + static const std::string ColorType = "Color"; static const std::string DiffuseColorToken = "diffuse"; static const std::string SpecularColorToken = "specular"; static const std::string EmissionColorToken = "emission"; @@ -112,7 +112,7 @@ namespace Grammar { TextureToken }; - static const char *ValidMetricToken[ 4 ] = { + static const std::string ValidMetricToken[ 4 ] = { Metric_DistanceType, Metric_AngleType, Metric_TimeType, @@ -126,7 +126,7 @@ namespace Grammar { int idx( -1 ); for( size_t i = 0; i < 4; i++ ) { - if( 0 == strncmp( ValidMetricToken[ i ], token, strlen( token ) ) ) { + if( ValidMetricToken[ i ] == token ) { idx = (int) i; break; } @@ -136,45 +136,33 @@ namespace Grammar { } static TokenType matchTokenType( const char *tokenType ) { - if( 0 == strncmp( MetricType, tokenType, strlen( MetricType ) ) ) { + if( MetricType == tokenType ) { return MetricToken; - } else if( 0 == strncmp( NameType, tokenType, strlen( NameType ) ) ) { + } else if( NameType == tokenType ) { return NameToken; - } - else if( 0 == strncmp( ObjectRefType, tokenType, strlen( ObjectRefType ) ) ) { + } else if( ObjectRefType == tokenType ) { return ObjectRefToken; - } - else if( 0 == strncmp( MaterialRefType, tokenType, strlen( MaterialRefType ) ) ) { + } else if( MaterialRefType == tokenType ) { return MaterialRefToken; - } - else if( 0 == strncmp( MetricKeyType, tokenType, strlen( MetricKeyType ) ) ) { + } else if( MetricKeyType == tokenType ) { return MetricKeyToken; - } - else if( 0 == strncmp( GeometryNodeType, tokenType, strlen( GeometryNodeType ) ) ) { + } else if( GeometryNodeType == tokenType ) { return GeometryNodeToken; - } - else if( 0 == strncmp( GeometryObjectType, tokenType, strlen( GeometryObjectType ) ) ) { + } else if( GeometryObjectType == tokenType ) { return GeometryObjectToken; - } - else if( 0 == strncmp( TransformType, tokenType, strlen( TransformType ) ) ) { + } else if( TransformType == tokenType ) { return TransformToken; - } - else if( 0 == strncmp( MeshType, tokenType, strlen( MeshType ) ) ) { + } else if( MeshType == tokenType ) { return MeshToken; - } - else if( 0 == strncmp( VertexArrayType, tokenType, strlen( VertexArrayType ) ) ) { + } else if( VertexArrayType == tokenType ) { return VertexArrayToken; - } - else if( 0 == strncmp( IndexArrayType, tokenType, strlen( IndexArrayType ) ) ) { + } else if( IndexArrayType == tokenType ) { return IndexArrayToken; - } - else if( 0 == strncmp( MaterialType, tokenType, strlen( MaterialType ) ) ) { + } else if( MaterialType == tokenType ) { return MaterialToken; - } - else if( 0 == strncmp( ColorType, tokenType, strlen( ColorType ) ) ) { + } else if( ColorType == tokenType ) { return ColorToken; - } - else if( 0 == strncmp( TextureType, tokenType, strlen( TextureType ) ) ) { + } else if( TextureType == tokenType ) { return TextureToken; } diff --git a/code/PlyExporter.cpp b/code/PlyExporter.cpp index 9268794f0..0a23e4b75 100644 --- a/code/PlyExporter.cpp +++ b/code/PlyExporter.cpp @@ -189,7 +189,12 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina } mOutput << "element face " << faces << endl; - mOutput << "property list uint uint vertex_index" << endl; + + // uchar seems to be the most common type for the number of indices per polygon and int seems to be most common for the vertex indices. + // For instance, MeshLab fails to load meshes in which both types are uint. Houdini seems to have problems as well. + // Obviously, using uchar will not work for meshes with polygons with more than 255 indices, but how realistic is this case? + mOutput << "property list uchar int vertex_index" << endl; + mOutput << "end_header" << endl; for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { @@ -342,16 +347,24 @@ void PlyExporter::WriteMeshIndices(const aiMesh* m, unsigned int offset) } } -void PlyExporter::WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset) +// Generic method in case we want to use different data types for the indices or make this configurable. +template +void WriteMeshIndicesBinary_Generic(const aiMesh* m, unsigned int offset, std::ostringstream& output) { for (unsigned int i = 0; i < m->mNumFaces; ++i) { const aiFace& f = m->mFaces[i]; - mOutput.write(reinterpret_cast(&f.mNumIndices), 4); + NumIndicesType numIndices = static_cast(f.mNumIndices); + output.write(reinterpret_cast(&numIndices), sizeof(NumIndicesType)); for (unsigned int c = 0; c < f.mNumIndices; ++c) { - unsigned int index = f.mIndices[c] + offset; - mOutput.write(reinterpret_cast(&index), 4); + IndexType index = f.mIndices[c] + offset; + output.write(reinterpret_cast(&index), sizeof(IndexType)); } } } +void PlyExporter::WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset) +{ + WriteMeshIndicesBinary_Generic(m, offset, mOutput); +} + #endif diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 65c9ba284..f86ddcead 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -310,6 +310,10 @@ void PLYImporter::ConvertMeshes(std::vector* avFaces, iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size(); } p_pcOut->mNumVertices = iNum; + if( 0 == iNum ) { // nothing to do + delete[] aiSplit; // cleanup + return; + } p_pcOut->mVertices = new aiVector3D[iNum]; if (!avColors->empty()) @@ -335,20 +339,25 @@ void PLYImporter::ConvertMeshes(std::vector* avFaces, for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) { p_pcOut->mFaces[iNum].mIndices[q] = iVertex; - p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]]; + const size_t idx = ( *avFaces )[ *i ].mIndices[ q ]; + if( idx >= ( *avPositions ).size() ) { + // out of border + continue; + } + p_pcOut->mVertices[ iVertex ] = ( *avPositions )[ idx ]; if (!avColors->empty()) - p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]]; + p_pcOut->mColors[ 0 ][ iVertex ] = ( *avColors )[ idx ]; if (!avTexCoords->empty()) { - const aiVector2D& vec = (*avTexCoords)[(*avFaces)[*i].mIndices[q]]; + const aiVector2D& vec = ( *avTexCoords )[ idx ]; p_pcOut->mTextureCoords[0][iVertex].x = vec.x; p_pcOut->mTextureCoords[0][iVertex].y = vec.y; } if (!avNormals->empty()) - p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]]; + p_pcOut->mNormals[ iVertex ] = ( *avNormals )[ idx ]; iVertex++; } diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index fb05be760..f840ce29c 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -75,8 +75,9 @@ static const aiImporterDesc desc = { // 2) 4 byte face count // 3) 50 bytes per face bool IsBinarySTL(const char* buffer, unsigned int fileSize) { - if (fileSize < 84) + if( fileSize < 84 ) { return false; + } const uint32_t faceCount = *reinterpret_cast(buffer + 80); const uint32_t expectedBinaryFileSize = faceCount * 50 + 84; @@ -99,7 +100,20 @@ bool IsAsciiSTL(const char* buffer, unsigned int fileSize) { if (buffer + 5 >= bufferEnd) return false; - return strncmp(buffer, "solid", 5) == 0; + bool isASCII( strncmp( buffer, "solid", 5 ) == 0 ); + if( isASCII ) { + // A lot of importers are write solid even if the file is binary. So we have to check for ASCII-characters. + if( fileSize >= 500 ) { + isASCII = true; + for( unsigned int i = 0; i < 500; i++ ) { + if( buffer[ i ] > 127 ) { + isASCII = false; + break; + } + } + } + } + return isASCII; } } // namespace @@ -122,23 +136,37 @@ bool STLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool { const std::string extension = GetExtension(pFile); - if (extension == "stl") + if( extension == "stl" ) { return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) + } else if (!extension.length() || checkSig) { + if( !pIOHandler ) { return true; + } const char* tokens[] = {"STL","solid"}; return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); } + return false; } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* STLImporter::GetInfo () const -{ +const aiImporterDesc* STLImporter::GetInfo () const { return &desc; } +void addFacesToMesh(aiMesh* pMesh) +{ + pMesh->mFaces = new aiFace[pMesh->mNumFaces]; + for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) { + + aiFace& face = pMesh->mFaces[i]; + face.mIndices = new unsigned int[face.mNumIndices = 3]; + for (unsigned int o = 0; o < 3;++o,++p) { + face.mIndices[o] = p; + } + } +} + // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. void STLImporter::InternReadFile( const std::string& pFile, @@ -164,17 +192,8 @@ void STLImporter::InternReadFile( const std::string& pFile, // the default vertex color is light gray. clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f; - // allocate one mesh - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh(); - pMesh->mMaterialIndex = 0; - // allocate a single node pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; bool bMatClr = false; @@ -186,16 +205,11 @@ void STLImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + "."); } - // now copy faces - pMesh->mFaces = new aiFace[pMesh->mNumFaces]; - for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) { - - aiFace& face = pMesh->mFaces[i]; - face.mIndices = new unsigned int[face.mNumIndices = 3]; - for (unsigned int o = 0; o < 3;++o,++p) { - face.mIndices[o] = p; - } - } + // add all created meshes to the single node + pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + for (unsigned int i = 0; i < pScene->mNumMeshes; i++) + pScene->mRootNode->mMeshes[i] = i; // create a single default material, using a light gray diffuse color for consistency with // other geometric types (e.g., PLY). @@ -221,140 +235,171 @@ void STLImporter::InternReadFile( const std::string& pFile, // Read an ASCII STL file void STLImporter::LoadASCIIFile() { - aiMesh* pMesh = pScene->mMeshes[0]; - + std::vector meshes; const char* sz = mBuffer; - SkipSpaces(&sz); - ai_assert(!IsLineEnd(sz)); - - sz += 5; // skip the "solid" - SkipSpaces(&sz); - const char* szMe = sz; - while (!::IsSpaceOrNewLine(*sz)) { - sz++; - } - - size_t temp; - // setup the name of the node - if ((temp = (size_t)(sz-szMe))) { - if (temp >= MAXLEN) { - throw DeadlyImportError( "STL: Node name too long" ); - } - - pScene->mRootNode->mName.length = temp; - memcpy(pScene->mRootNode->mName.data,szMe,temp); - pScene->mRootNode->mName.data[temp] = '\0'; - } - else pScene->mRootNode->mName.Set(""); + const char* bufferEnd = mBuffer + fileSize; + std::vector positionBuffer; + std::vector normalBuffer; // try to guess how many vertices we could have // assume we'll need 160 bytes for each face - pMesh->mNumVertices = ( pMesh->mNumFaces = std::max(1u,fileSize / 160u )) * 3; - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + size_t sizeEstimate = std::max(1u, fileSize / 160u ) * 3; + positionBuffer.reserve(sizeEstimate); + normalBuffer.reserve(sizeEstimate); - unsigned int curFace = 0, curVertex = 3; - for ( ;; ) + while (IsAsciiSTL(sz, bufferEnd - sz)) { - // go to the next token - if(!SkipSpacesAndLineEnd(&sz)) + aiMesh* pMesh = new aiMesh(); + pMesh->mMaterialIndex = 0; + meshes.push_back(pMesh); + + SkipSpaces(&sz); + ai_assert(!IsLineEnd(sz)); + + sz += 5; // skip the "solid" + SkipSpaces(&sz); + const char* szMe = sz; + while (!::IsSpaceOrNewLine(*sz)) { + sz++; + } + + size_t temp; + // setup the name of the node + if ((temp = (size_t)(sz-szMe))) { + if (temp >= MAXLEN) { + throw DeadlyImportError( "STL: Node name too long" ); + } + + pScene->mRootNode->mName.length = temp; + memcpy(pScene->mRootNode->mName.data,szMe,temp); + pScene->mRootNode->mName.data[temp] = '\0'; + } + else pScene->mRootNode->mName.Set(""); + + unsigned int faceVertexCounter = 0; + for ( ;; ) { - // seems we're finished although there was no end marker - DefaultLogger::get()->warn("STL: unexpected EOF. \'endsolid\' keyword was expected"); - break; - } - // facet normal -0.13 -0.13 -0.98 - if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5))) { - - if (3 != curVertex) { - DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete"); - } - if (pMesh->mNumFaces == curFace) { - ai_assert(pMesh->mNumFaces != 0); - - // need to resize the arrays, our size estimate was wrong - unsigned int iNeededSize = (unsigned int)(sz-mBuffer) / pMesh->mNumFaces; - if (iNeededSize <= 160)iNeededSize >>= 1; // prevent endless looping - unsigned int add = (unsigned int)((mBuffer+fileSize)-sz) / iNeededSize; - add += add >> 3; // add 12.5% as buffer - iNeededSize = (pMesh->mNumFaces + add)*3; - aiVector3D* pv = new aiVector3D[iNeededSize]; - memcpy(pv,pMesh->mVertices,pMesh->mNumVertices*sizeof(aiVector3D)); - delete[] pMesh->mVertices; - pMesh->mVertices = pv; - pv = new aiVector3D[iNeededSize]; - memcpy(pv,pMesh->mNormals,pMesh->mNumVertices*sizeof(aiVector3D)); - delete[] pMesh->mNormals; - pMesh->mNormals = pv; - - pMesh->mNumVertices = iNeededSize; - pMesh->mNumFaces += add; - } - aiVector3D* vn = &pMesh->mNormals[curFace++*3]; - - sz += 6; - curVertex = 0; - SkipSpaces(&sz); - if (strncmp(sz,"normal",6)) { - DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); - } - else + // go to the next token + if(!SkipSpacesAndLineEnd(&sz)) { - sz += 7; - SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (float&)vn->x ); - SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (float&)vn->y ); - SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (float&)vn->z ); - *(vn+1) = *vn; - *(vn+2) = *vn; + // seems we're finished although there was no end marker + DefaultLogger::get()->warn("STL: unexpected EOF. \'endsolid\' keyword was expected"); + break; } - } - // vertex 1.50000 1.50000 0.00000 - else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) - { - if (3 == curVertex) { - DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); - ++sz; - } - else - { - sz += 7; - SkipSpaces(&sz); - aiVector3D* vn = &pMesh->mVertices[(curFace-1)*3 + curVertex++]; - sz = fast_atoreal_move(sz, (float&)vn->x ); - SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (float&)vn->y ); - SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (float&)vn->z ); - } - } - else if (!::strncmp(sz,"endsolid",8)) { - // finished! - break; - } - // else skip the whole identifier - else { - do { - ++sz; - } while (!::IsSpaceOrNewLine(*sz)); - } - } + // facet normal -0.13 -0.13 -0.98 + if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5)) && *(sz + 5) != '\0') { - if (!curFace) { - pMesh->mNumFaces = 0; - throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded"); + if (faceVertexCounter != 3) { + DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete"); + } + faceVertexCounter = 0; + normalBuffer.push_back(aiVector3D()); + aiVector3D* vn = &normalBuffer.back(); + + sz += 6; + SkipSpaces(&sz); + if (strncmp(sz,"normal",6)) { + DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); + } + else + { + if (sz[6] == '\0') { + throw DeadlyImportError("STL: unexpected EOF while parsing facet"); + } + sz += 7; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (float&)vn->x ); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (float&)vn->y ); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (float&)vn->z ); + normalBuffer.push_back(*vn); + normalBuffer.push_back(*vn); + } + } + // vertex 1.50000 1.50000 0.00000 + else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) + { + if (faceVertexCounter >= 3) { + DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); + ++sz; + } + else + { + if (sz[6] == '\0') { + throw DeadlyImportError("STL: unexpected EOF while parsing facet"); + } + sz += 7; + SkipSpaces(&sz); + positionBuffer.push_back(aiVector3D()); + aiVector3D* vn = &positionBuffer.back(); + sz = fast_atoreal_move(sz, (float&)vn->x ); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (float&)vn->y ); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (float&)vn->z ); + faceVertexCounter++; + } + } + else if (!::strncmp(sz,"endsolid",8)) { + do { + ++sz; + } while (!::IsLineEnd(*sz)); + SkipSpacesAndLineEnd(&sz); + // finished! + break; + } + // else skip the whole identifier + else { + do { + ++sz; + } while (!::IsSpaceOrNewLine(*sz)); + } + } + + if (positionBuffer.empty()) { + pMesh->mNumFaces = 0; + throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded"); + } + if (positionBuffer.size() % 3 != 0) { + pMesh->mNumFaces = 0; + throw DeadlyImportError("STL: Invalid number of vertices"); + } + if (normalBuffer.size() != positionBuffer.size()) { + pMesh->mNumFaces = 0; + throw DeadlyImportError("Normal buffer size does not match position buffer size"); + } + pMesh->mNumFaces = positionBuffer.size() / 3; + pMesh->mNumVertices = positionBuffer.size(); + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + positionBuffer.clear(); + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + normalBuffer.clear(); + + // now copy faces + addFacesToMesh(pMesh); + } + // now add the loaded meshes + pScene->mNumMeshes = (unsigned int)meshes.size(); + pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + for (size_t i = 0; i < meshes.size(); i++) + { + pScene->mMeshes[i] = meshes[i]; } - pMesh->mNumFaces = curFace; - pMesh->mNumVertices = curFace*3; - // we are finished! } // ------------------------------------------------------------------------------------------------ // Read a binary STL file bool STLImporter::LoadBinaryFile() { + // allocate one mesh + pScene->mNumMeshes = 1; + pScene->mMeshes = new aiMesh*[1]; + aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh(); + pMesh->mMaterialIndex = 0; + // skip the first 80 bytes if (fileSize < 84) { throw DeadlyImportError("STL: file is too small for the header"); @@ -382,7 +427,6 @@ bool STLImporter::LoadBinaryFile() const unsigned char* sz = (const unsigned char*)mBuffer + 80; // now read the number of facets - aiMesh* pMesh = pScene->mMeshes[0]; pScene->mRootNode->mName.Set(""); pMesh->mNumFaces = *((uint32_t*)sz); @@ -402,7 +446,7 @@ bool STLImporter::LoadBinaryFile() vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - for (unsigned int i = 0; i < pMesh->mNumFaces;++i) { + for (unsigned int i = 0; i < pMesh->mNumFaces;++i) { // NOTE: Blender sometimes writes empty normals ... this is not // our fault ... the RemoveInvalidData helper step should fix that @@ -455,6 +499,10 @@ bool STLImporter::LoadBinaryFile() *(clr+2) = *clr; } } + + // now copy faces + addFacesToMesh(pMesh); + if (bIsMaterialise && !pMesh->mColors[0]) { // use the color as diffuse material color diff --git a/code/Subdivision.cpp b/code/Subdivision.cpp index 2c1c2ea7d..1443f46eb 100644 --- a/code/Subdivision.cpp +++ b/code/Subdivision.cpp @@ -399,10 +399,14 @@ void CatmullClarkSubdivider::InternSubdivide ( bool haveit = false; for (unsigned int i = 0; i < f.mNumIndices; ++i) { if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) { - haveit = true; break; + haveit = true; + break; } } ai_assert(haveit); + if (!haveit) { + DefaultLogger::get()->debug("Catmull-Clark Subdivider: Index not used"); + } break; } } diff --git a/code/res/resource.h b/code/res/resource.h index 41ce1c5ee..37d39284f 100644 --- a/code/res/resource.h +++ b/code/res/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by assimp.rc - -// Nächste Standardwerte für neue Objekte -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by assimp.rc + +// Nächste Standardwerte für neue Objekte +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/contrib/clipper/License.txt b/contrib/clipper/License.txt index 51acabf74..8e2278cef 100644 --- a/contrib/clipper/License.txt +++ b/contrib/clipper/License.txt @@ -1,29 +1,29 @@ -The Clipper code library, the "Software" (that includes Delphi, C++ & C# -source code, accompanying samples and documentation), has been released -under the following license, terms and conditions: - -Boost Software License - Version 1.0 - August 17th, 2003 -http://www.boost.org/LICENSE_1_0.txt - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - +The Clipper code library, the "Software" (that includes Delphi, C++ & C# +source code, accompanying samples and documentation), has been released +under the following license, terms and conditions: + +Boost Software License - Version 1.0 - August 17th, 2003 +http://www.boost.org/LICENSE_1_0.txt + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index 1efa01df8..b2316ccd5 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -1,3448 +1,3448 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 4.8.8 * -* Date : 30 August 2012 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2012 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -/******************************************************************************* -* * -* This is a translation of the Delphi Clipper library and the naming style * -* used has retained a Delphi flavour. * -* * -*******************************************************************************/ - -#include "clipper.hpp" -#include -#include -#include -#include -#include -#include -#include - -namespace ClipperLib { - -static long64 const loRange = 0x3FFFFFFF; -static long64 const hiRange = 0x3FFFFFFFFFFFFFFFLL; -static double const pi = 3.141592653589793238; -enum Direction { dRightToLeft, dLeftToRight }; - -#define HORIZONTAL (-1.0E+40) -#define TOLERANCE (1.0e-20) -#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) -#define NEAR_EQUAL(a, b) NEAR_ZERO((a) - (b)) - -inline long64 Abs(long64 val) -{ - return val < 0 ? -val : val; -} -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -// Int128 class (enables safe math on signed 64bit integers) -// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 -// Int128 val2((long64)9223372036854775807); -// Int128 val3 = val1 * val2; -// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) -//------------------------------------------------------------------------------ - -class Int128 -{ - public: - - Int128(long64 _lo = 0) - { - lo = _lo; - if (lo < 0) hi = -1; else hi = 0; - } - - Int128(const Int128 &val): hi(val.hi), lo(val.lo){} - - long64 operator = (const long64 &val) - { - lo = val; - if (lo < 0) hi = -1; else hi = 0; - return val; - } - - bool operator == (const Int128 &val) const - {return (hi == val.hi && lo == val.lo);} - - bool operator != (const Int128 &val) const - { return !(*this == val);} - - bool operator > (const Int128 &val) const - { - if (hi != val.hi) - return hi > val.hi; - else - return lo > val.lo; - } - - bool operator < (const Int128 &val) const - { - if (hi != val.hi) - return hi < val.hi; - else - return lo < val.lo; - } - - bool operator >= (const Int128 &val) const - { return !(*this < val);} - - bool operator <= (const Int128 &val) const - { return !(*this > val);} - - Int128& operator += (const Int128 &rhs) - { - hi += rhs.hi; - lo += rhs.lo; - if (ulong64(lo) < ulong64(rhs.lo)) hi++; - return *this; - } - - Int128 operator + (const Int128 &rhs) const - { - Int128 result(*this); - result+= rhs; - return result; - } - - Int128& operator -= (const Int128 &rhs) - { - Int128 tmp(rhs); - Negate(tmp); - *this += tmp; - return *this; - } - - //Int128 operator -() const - //{ - // Int128 result(*this); - // if (result.lo == 0) { - // if (result.hi != 0) result.hi = -1; - // } - // else { - // result.lo = -result.lo; - // result.hi = ~result.hi; - // } - // return result; - //} - - Int128 operator - (const Int128 &rhs) const - { - Int128 result(*this); - result -= rhs; - return result; - } - - Int128 operator * (const Int128 &rhs) const - { - if ( !(hi == 0 || hi == -1) || !(rhs.hi == 0 || rhs.hi == -1)) - throw "Int128 operator*: overflow error"; - bool negate = (hi < 0) != (rhs.hi < 0); - - Int128 tmp(*this); - if (tmp.hi < 0) Negate(tmp); - ulong64 int1Hi = ulong64(tmp.lo) >> 32; - ulong64 int1Lo = ulong64(tmp.lo & 0xFFFFFFFF); - - tmp = rhs; - if (tmp.hi < 0) Negate(tmp); - ulong64 int2Hi = ulong64(tmp.lo) >> 32; - ulong64 int2Lo = ulong64(tmp.lo & 0xFFFFFFFF); - - //nb: see comments in clipper.pas - ulong64 a = int1Hi * int2Hi; - ulong64 b = int1Lo * int2Lo; - ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; - - tmp.hi = long64(a + (c >> 32)); - tmp.lo = long64(c << 32); - tmp.lo += long64(b); - if (ulong64(tmp.lo) < b) tmp.hi++; - if (negate) Negate(tmp); - return tmp; - } - - Int128 operator/ (const Int128 &rhs) const - { - if (rhs.lo == 0 && rhs.hi == 0) - throw "Int128 operator/: divide by zero"; - bool negate = (rhs.hi < 0) != (hi < 0); - Int128 result(*this), denom(rhs); - if (result.hi < 0) Negate(result); - if (denom.hi < 0) Negate(denom); - if (denom > result) return Int128(0); //result is only a fraction of 1 - Negate(denom); - - Int128 p(0); - for (int i = 0; i < 128; ++i) - { - p.hi = p.hi << 1; - if (p.lo < 0) p.hi++; - p.lo = long64(p.lo) << 1; - if (result.hi < 0) p.lo++; - result.hi = result.hi << 1; - if (result.lo < 0) result.hi++; - result.lo = long64(result.lo) << 1; - Int128 p2(p); - p += denom; - if (p.hi < 0) p = p2; - else result.lo++; - } - if (negate) Negate(result); - return result; - } - - double AsDouble() const - { - const double shift64 = 18446744073709551616.0; //2^64 - const double bit64 = 9223372036854775808.0; - if (hi < 0) - { - Int128 tmp(*this); - Negate(tmp); - if (tmp.lo < 0) - return (double)tmp.lo - bit64 - tmp.hi * shift64; - else - return -(double)tmp.lo - tmp.hi * shift64; - } - else if (lo < 0) - return -(double)lo + bit64 + hi * shift64; - else - return (double)lo + (double)hi * shift64; - } - - //for bug testing ... - //std::string AsString() const - //{ - // std::string result; - // unsigned char r = 0; - // Int128 tmp(0), val(*this); - // if (hi < 0) Negate(val); - // result.resize(50); - // std::string::size_type i = result.size() -1; - // while (val.hi != 0 || val.lo != 0) - // { - // Div10(val, tmp, r); - // result[i--] = char('0' + r); - // val = tmp; - // } - // if (hi < 0) result[i--] = '-'; - // result.erase(0,i+1); - // if (result.size() == 0) result = "0"; - // return result; - //} - -private: - long64 hi; - long64 lo; - - static void Negate(Int128 &val) - { - if (val.lo == 0) { - if (val.hi != 0) val.hi = -val.hi;; - } - else { - val.lo = -val.lo; - val.hi = ~val.hi; - } - } - - //debugging only ... - //void Div10(const Int128 val, Int128& result, unsigned char & remainder) const - //{ - // remainder = 0; - // result = 0; - // for (int i = 63; i >= 0; --i) - // { - // if ((val.hi & ((long64)1 << i)) != 0) - // remainder = char((remainder * 2) + 1); else - // remainder *= char(2); - // if (remainder >= 10) - // { - // result.hi += ((long64)1 << i); - // remainder -= char(10); - // } - // } - // for (int i = 63; i >= 0; --i) - // { - // if ((val.lo & ((long64)1 << i)) != 0) - // remainder = char((remainder * 2) + 1); else - // remainder *= char(2); - // if (remainder >= 10) - // { - // result.lo += ((long64)1 << i); - // remainder -= char(10); - // } - // } - //} -}; - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -bool FullRangeNeeded(const Polygon &pts) -{ - bool result = false; - for (Polygon::size_type i = 0; i < pts.size(); ++i) - { - if (Abs(pts[i].X) > hiRange || Abs(pts[i].Y) > hiRange) - throw "Coordinate exceeds range bounds."; - else if (Abs(pts[i].X) > loRange || Abs(pts[i].Y) > loRange) - result = true; - } - return result; -} -//------------------------------------------------------------------------------ - -bool Orientation(const Polygon &poly) -{ - int highI = (int)poly.size() -1; - if (highI < 2) return false; - - int j = 0, jplus, jminus; - for (int i = 0; i <= highI; ++i) - { - if (poly[i].Y < poly[j].Y) continue; - if ((poly[i].Y > poly[j].Y || poly[i].X < poly[j].X)) j = i; - }; - if (j == highI) jplus = 0; - else jplus = j +1; - if (j == 0) jminus = highI; - else jminus = j -1; - - IntPoint vec1, vec2; - //get cross product of vectors of the edges adjacent to highest point ... - vec1.X = poly[j].X - poly[jminus].X; - vec1.Y = poly[j].Y - poly[jminus].Y; - vec2.X = poly[jplus].X - poly[j].X; - vec2.Y = poly[jplus].Y - poly[j].Y; - - if (Abs(vec1.X) > loRange || Abs(vec1.Y) > loRange || - Abs(vec2.X) > loRange || Abs(vec2.Y) > loRange) - { - if (Abs(vec1.X) > hiRange || Abs(vec1.Y) > hiRange || - Abs(vec2.X) > hiRange || Abs(vec2.Y) > hiRange) - throw "Coordinate exceeds range bounds."; - Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - - Int128(vec2.X) * Int128(vec1.Y); - return cross >= 0; - } - else - return (vec1.X * vec2.Y - vec2.X * vec1.Y) >= 0; -} -//------------------------------------------------------------------------------ - -inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) -{ - return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); -} -//------------------------------------------------------------------------------ - -bool Orientation(OutRec *outRec, bool UseFullInt64Range) -{ - //first make sure bottomPt is correctly assigned ... - OutPt *opBottom = outRec->pts, *op = outRec->pts->next; - while (op != outRec->pts) - { - if (op->pt.Y >= opBottom->pt.Y) - { - if (op->pt.Y > opBottom->pt.Y || op->pt.X < opBottom->pt.X) - opBottom = op; - } - op = op->next; - } - outRec->bottomPt = opBottom; - opBottom->idx = outRec->idx; - - op = opBottom; - //find vertices either side of bottomPt (skipping duplicate points) .... - OutPt *opPrev = op->prev; - OutPt *opNext = op->next; - while (op != opPrev && PointsEqual(op->pt, opPrev->pt)) - opPrev = opPrev->prev; - while (op != opNext && PointsEqual(op->pt, opNext->pt)) - opNext = opNext->next; - - IntPoint ip1, ip2; - ip1.X = op->pt.X - opPrev->pt.X; - ip1.Y = op->pt.Y - opPrev->pt.Y; - ip2.X = opNext->pt.X - op->pt.X; - ip2.Y = opNext->pt.Y - op->pt.Y; - - if (UseFullInt64Range) - return Int128(ip1.X) * Int128(ip2.Y) - Int128(ip2.X) * Int128(ip1.Y) >= 0; - else - return (ip1.X * ip2.Y - ip2.X * ip1.Y) >= 0; -} -//------------------------------------------------------------------------------ - -double Area(const Polygon &poly) -{ - int highI = (int)poly.size() -1; - if (highI < 2) return 0; - - if (FullRangeNeeded(poly)) { - Int128 a; - a = (Int128(poly[highI].X) * Int128(poly[0].Y)) - - Int128(poly[0].X) * Int128(poly[highI].Y); - for (int i = 0; i < highI; ++i) - a += Int128(poly[i].X) * Int128(poly[i+1].Y) - - Int128(poly[i+1].X) * Int128(poly[i].Y); - return a.AsDouble() / 2; - } - else - { - double a; - a = (double)poly[highI].X * poly[0].Y - (double)poly[0].X * poly[highI].Y; - for (int i = 0; i < highI; ++i) - a += (double)poly[i].X * poly[i+1].Y - (double)poly[i+1].X * poly[i].Y; - return a/2; - } -} -//------------------------------------------------------------------------------ - -double Area(const OutRec &outRec, bool UseFullInt64Range) -{ - OutPt *op = outRec.pts; - if (UseFullInt64Range) { - Int128 a(0); - do { - a += (Int128(op->prev->pt.X) * Int128(op->pt.Y)) - - Int128(op->pt.X) * Int128(op->prev->pt.Y); - op = op->next; - } while (op != outRec.pts); - return a.AsDouble() / 2; - } - else - { - double a = 0; - do { - a += (op->prev->pt.X * op->pt.Y) - (op->pt.X * op->prev->pt.Y); - op = op->next; - } while (op != outRec.pts); - return a/2; - } -} -//------------------------------------------------------------------------------ - -bool PointIsVertex(const IntPoint &pt, OutPt *pp) -{ - OutPt *pp2 = pp; - do - { - if (PointsEqual(pp2->pt, pt)) return true; - pp2 = pp2->next; - } - while (pp2 != pp); - return false; -} -//------------------------------------------------------------------------------ - -bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range) -{ - OutPt *pp2 = pp; - bool result = false; - if (UseFullInt64Range) { - do - { - if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || - ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && - Int128(pt.X - pp2->pt.X) < (Int128(pp2->prev->pt.X - pp2->pt.X) * - Int128(pt.Y - pp2->pt.Y)) / Int128(pp2->prev->pt.Y - pp2->pt.Y)) - result = !result; - pp2 = pp2->next; - } - while (pp2 != pp); - } - else - { - do - { - if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || - ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && - (pt.X < (pp2->prev->pt.X - pp2->pt.X) * (pt.Y - pp2->pt.Y) / - (pp2->prev->pt.Y - pp2->pt.Y) + pp2->pt.X )) result = !result; - pp2 = pp2->next; - } - while (pp2 != pp); - } - return result; -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(TEdge &e1, TEdge &e2, bool UseFullInt64Range) -{ - if (UseFullInt64Range) - return Int128(e1.ytop - e1.ybot) * Int128(e2.xtop - e2.xbot) == - Int128(e1.xtop - e1.xbot) * Int128(e2.ytop - e2.ybot); - else return (e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) == - (e1.xtop - e1.xbot)*(e2.ytop - e2.ybot); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, bool UseFullInt64Range) -{ - if (UseFullInt64Range) - return Int128(pt1.Y-pt2.Y) * Int128(pt2.X-pt3.X) == - Int128(pt1.X-pt2.X) * Int128(pt2.Y-pt3.Y); - else return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) -{ - if (UseFullInt64Range) - return Int128(pt1.Y-pt2.Y) * Int128(pt3.X-pt4.X) == - Int128(pt1.X-pt2.X) * Int128(pt3.Y-pt4.Y); - else return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); -} -//------------------------------------------------------------------------------ - -double GetDx(const IntPoint pt1, const IntPoint pt2) -{ - return (pt1.Y == pt2.Y) ? - HORIZONTAL : (double)(pt2.X - pt1.X) / (double)(pt2.Y - pt1.Y); -} -//--------------------------------------------------------------------------- - -void SetDx(TEdge &e) -{ - if (e.ybot == e.ytop) e.dx = HORIZONTAL; - else e.dx = (double)(e.xtop - e.xbot) / (double)(e.ytop - e.ybot); -} -//--------------------------------------------------------------------------- - -void SwapSides(TEdge &edge1, TEdge &edge2) -{ - EdgeSide side = edge1.side; - edge1.side = edge2.side; - edge2.side = side; -} -//------------------------------------------------------------------------------ - -void SwapPolyIndexes(TEdge &edge1, TEdge &edge2) -{ - int outIdx = edge1.outIdx; - edge1.outIdx = edge2.outIdx; - edge2.outIdx = outIdx; -} -//------------------------------------------------------------------------------ - -inline long64 Round(double val) -{ - return (val < 0) ? - static_cast(val - 0.5) : static_cast(val + 0.5); -} -//------------------------------------------------------------------------------ - -long64 TopX(TEdge &edge, const long64 currentY) -{ - return ( currentY == edge.ytop ) ? - edge.xtop : edge.xbot + Round(edge.dx *(currentY - edge.ybot)); -} -//------------------------------------------------------------------------------ - -long64 TopX(const IntPoint pt1, const IntPoint pt2, const long64 currentY) -{ - //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y - if (currentY >= pt1.Y) return pt1.X; - else if (currentY == pt2.Y) return pt2.X; - else if (pt1.X == pt2.X) return pt1.X; - else - { - double q = (double)(pt1.X-pt2.X)/(double)(pt1.Y-pt2.Y); - return Round(pt1.X + (currentY - pt1.Y) *q); - } -} -//------------------------------------------------------------------------------ - -bool IntersectPoint(TEdge &edge1, TEdge &edge2, - IntPoint &ip, bool UseFullInt64Range) -{ - double b1, b2; - if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false; - else if (NEAR_ZERO(edge1.dx)) - { - ip.X = edge1.xbot; - if (NEAR_EQUAL(edge2.dx, HORIZONTAL)) - { - ip.Y = edge2.ybot; - } else - { - b2 = edge2.ybot - (edge2.xbot/edge2.dx); - ip.Y = Round(ip.X/edge2.dx + b2); - } - } - else if (NEAR_ZERO(edge2.dx)) - { - ip.X = edge2.xbot; - if (NEAR_EQUAL(edge1.dx, HORIZONTAL)) - { - ip.Y = edge1.ybot; - } else - { - b1 = edge1.ybot - (edge1.xbot/edge1.dx); - ip.Y = Round(ip.X/edge1.dx + b1); - } - } else - { - b1 = edge1.xbot - edge1.ybot * edge1.dx; - b2 = edge2.xbot - edge2.ybot * edge2.dx; - b2 = (b2-b1)/(edge1.dx - edge2.dx); - ip.Y = Round(b2); - ip.X = Round(edge1.dx * b2 + b1); - } - - return - //can be *so close* to the top of one edge that the rounded Y equals one ytop ... - (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) || - (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) || - (ip.Y > edge1.ytop && ip.Y > edge2.ytop); -} -//------------------------------------------------------------------------------ - -void ReversePolyPtLinks(OutPt &pp) -{ - OutPt *pp1, *pp2; - pp1 = &pp; - do { - pp2 = pp1->next; - pp1->next = pp1->prev; - pp1->prev = pp2; - pp1 = pp2; - } while( pp1 != &pp ); -} -//------------------------------------------------------------------------------ - -void DisposeOutPts(OutPt*& pp) -{ - if (pp == 0) return; - pp->prev->next = 0; - while( pp ) - { - OutPt *tmpPp = pp; - pp = pp->next; - delete tmpPp ; - } -} -//------------------------------------------------------------------------------ - -void InitEdge(TEdge *e, TEdge *eNext, - TEdge *ePrev, const IntPoint &pt, PolyType polyType) -{ - std::memset( e, 0, sizeof( TEdge )); - - e->next = eNext; - e->prev = ePrev; - e->xcurr = pt.X; - e->ycurr = pt.Y; - if (e->ycurr >= e->next->ycurr) - { - e->xbot = e->xcurr; - e->ybot = e->ycurr; - e->xtop = e->next->xcurr; - e->ytop = e->next->ycurr; - e->windDelta = 1; - } else - { - e->xtop = e->xcurr; - e->ytop = e->ycurr; - e->xbot = e->next->xcurr; - e->ybot = e->next->ycurr; - e->windDelta = -1; - } - SetDx(*e); - e->polyType = polyType; - e->outIdx = -1; -} -//------------------------------------------------------------------------------ - -inline void SwapX(TEdge &e) -{ - //swap horizontal edges' top and bottom x's so they follow the natural - //progression of the bounds - ie so their xbots will align with the - //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] - e.xcurr = e.xtop; - e.xtop = e.xbot; - e.xbot = e.xcurr; -} -//------------------------------------------------------------------------------ - -void SwapPoints(IntPoint &pt1, IntPoint &pt2) -{ - IntPoint tmp = pt1; - pt1 = pt2; - pt2 = tmp; -} -//------------------------------------------------------------------------------ - -bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, - IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) -{ - //precondition: segments are colinear. - if ( pt1a.Y == pt1b.Y || Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 ) - { - if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); - if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); - if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; - return pt1.X < pt2.X; - } else - { - if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); - if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); - if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; - return pt1.Y > pt2.Y; - } -} -//------------------------------------------------------------------------------ - -bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) -{ - OutPt *p = btmPt1->prev; - while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->prev; - double dx1p = std::fabs(GetDx(btmPt1->pt, p->pt)); - p = btmPt1->next; - while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->next; - double dx1n = std::fabs(GetDx(btmPt1->pt, p->pt)); - - p = btmPt2->prev; - while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->prev; - double dx2p = std::fabs(GetDx(btmPt2->pt, p->pt)); - p = btmPt2->next; - while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->next; - double dx2n = std::fabs(GetDx(btmPt2->pt, p->pt)); - return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); -} -//------------------------------------------------------------------------------ - -OutPt* GetBottomPt(OutPt *pp) -{ - OutPt* dups = 0; - OutPt* p = pp->next; - while (p != pp) - { - if (p->pt.Y > pp->pt.Y) - { - pp = p; - dups = 0; - } - else if (p->pt.Y == pp->pt.Y && p->pt.X <= pp->pt.X) - { - if (p->pt.X < pp->pt.X) - { - dups = 0; - pp = p; - } else - { - if (p->next != pp && p->prev != pp) dups = p; - } - } - p = p->next; - } - if (dups) - { - //there appears to be at least 2 vertices at bottomPt so ... - while (dups != p) - { - if (!FirstIsBottomPt(p, dups)) pp = dups; - dups = dups->next; - while (!PointsEqual(dups->pt, pp->pt)) dups = dups->next; - } - } - return pp; -} -//------------------------------------------------------------------------------ - -bool FindSegment(OutPt* &pp, IntPoint &pt1, IntPoint &pt2) -{ - //outPt1 & outPt2 => the overlap segment (if the function returns true) - if (!pp) return false; - OutPt* pp2 = pp; - IntPoint pt1a = pt1, pt2a = pt2; - do - { - if (SlopesEqual(pt1a, pt2a, pp->pt, pp->prev->pt, true) && - SlopesEqual(pt1a, pt2a, pp->pt, true) && - GetOverlapSegment(pt1a, pt2a, pp->pt, pp->prev->pt, pt1, pt2)) - return true; - pp = pp->next; - } - while (pp != pp2); - return false; -} -//------------------------------------------------------------------------------ - -bool Pt3IsBetweenPt1AndPt2(const IntPoint pt1, - const IntPoint pt2, const IntPoint pt3) -{ - if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; - else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); - else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); -} -//------------------------------------------------------------------------------ - -OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint pt) -{ - if (p1 == p2) throw "JoinError"; - OutPt* result = new OutPt; - result->pt = pt; - if (p2 == p1->next) - { - p1->next = result; - p2->prev = result; - result->next = p2; - result->prev = p1; - } else - { - p2->next = result; - p1->prev = result; - result->next = p1; - result->prev = p2; - } - return result; -} - -//------------------------------------------------------------------------------ -// ClipperBase class methods ... -//------------------------------------------------------------------------------ - -ClipperBase::ClipperBase() //constructor -{ - m_MinimaList = 0; - m_CurrentLM = 0; - m_UseFullRange = true; -} -//------------------------------------------------------------------------------ - -ClipperBase::~ClipperBase() //destructor -{ - Clear(); -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType) -{ - int len = (int)pg.size(); - if (len < 3) return false; - Polygon p(len); - p[0] = pg[0]; - int j = 0; - - long64 maxVal; - if (m_UseFullRange) maxVal = hiRange; else maxVal = loRange; - - for (int i = 0; i < len; ++i) - { - if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) - { - if (Abs(pg[i].X) > hiRange || Abs(pg[i].Y) > hiRange) - throw "Coordinate exceeds range bounds"; - maxVal = hiRange; - m_UseFullRange = true; - } - - if (i == 0 || PointsEqual(p[j], pg[i])) continue; - else if (j > 0 && SlopesEqual(p[j-1], p[j], pg[i], m_UseFullRange)) - { - if (PointsEqual(p[j-1], pg[i])) j--; - } else j++; - p[j] = pg[i]; - } - if (j < 2) return false; - - len = j+1; - while (len > 2) - { - //nb: test for point equality before testing slopes ... - if (PointsEqual(p[j], p[0])) j--; - else if (PointsEqual(p[0], p[1]) || - SlopesEqual(p[j], p[0], p[1], m_UseFullRange)) - p[0] = p[j--]; - else if (SlopesEqual(p[j-1], p[j], p[0], m_UseFullRange)) j--; - else if (SlopesEqual(p[0], p[1], p[2], m_UseFullRange)) - { - for (int i = 2; i <= j; ++i) p[i-1] = p[i]; - j--; - } - else break; - len--; - } - if (len < 3) return false; - - //create a new edge array ... - TEdge *edges = new TEdge [len]; - m_edges.push_back(edges); - - //convert vertices to a double-linked-list of edges and initialize ... - edges[0].xcurr = p[0].X; - edges[0].ycurr = p[0].Y; - InitEdge(&edges[len-1], &edges[0], &edges[len-2], p[len-1], polyType); - for (int i = len-2; i > 0; --i) - InitEdge(&edges[i], &edges[i+1], &edges[i-1], p[i], polyType); - InitEdge(&edges[0], &edges[1], &edges[len-1], p[0], polyType); - - //reset xcurr & ycurr and find 'eHighest' (given the Y axis coordinates - //increase downward so the 'highest' edge will have the smallest ytop) ... - TEdge *e = &edges[0]; - TEdge *eHighest = e; - do - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - if (e->ytop < eHighest->ytop) eHighest = e; - e = e->next; - } - while ( e != &edges[0]); - - //make sure eHighest is positioned so the following loop works safely ... - if (eHighest->windDelta > 0) eHighest = eHighest->next; - if (NEAR_EQUAL(eHighest->dx, HORIZONTAL)) eHighest = eHighest->next; - - //finally insert each local minima ... - e = eHighest; - do { - e = AddBoundsToLML(e); - } - while( e != eHighest ); - return true; -} -//------------------------------------------------------------------------------ - -void ClipperBase::InsertLocalMinima(LocalMinima *newLm) -{ - if( ! m_MinimaList ) - { - m_MinimaList = newLm; - } - else if( newLm->Y >= m_MinimaList->Y ) - { - newLm->next = m_MinimaList; - m_MinimaList = newLm; - } else - { - LocalMinima* tmpLm = m_MinimaList; - while( tmpLm->next && ( newLm->Y < tmpLm->next->Y ) ) - tmpLm = tmpLm->next; - newLm->next = tmpLm->next; - tmpLm->next = newLm; - } -} -//------------------------------------------------------------------------------ - -TEdge* ClipperBase::AddBoundsToLML(TEdge *e) -{ - //Starting at the top of one bound we progress to the bottom where there's - //a local minima. We then go to the top of the next bound. These two bounds - //form the left and right (or right and left) bounds of the local minima. - e->nextInLML = 0; - e = e->next; - for (;;) - { - if (NEAR_EQUAL(e->dx, HORIZONTAL)) - { - //nb: proceed through horizontals when approaching from their right, - // but break on horizontal minima if approaching from their left. - // This ensures 'local minima' are always on the left of horizontals. - if (e->next->ytop < e->ytop && e->next->xbot > e->prev->xbot) break; - if (e->xtop != e->prev->xbot) SwapX(*e); - e->nextInLML = e->prev; - } - else if (e->ycurr == e->prev->ycurr) break; - else e->nextInLML = e->prev; - e = e->next; - } - - //e and e.prev are now at a local minima ... - LocalMinima* newLm = new LocalMinima; - newLm->next = 0; - newLm->Y = e->prev->ybot; - - if ( NEAR_EQUAL(e->dx, HORIZONTAL) ) //horizontal edges never start a left bound - { - if (e->xbot != e->prev->xbot) SwapX(*e); - newLm->leftBound = e->prev; - newLm->rightBound = e; - } else if (e->dx < e->prev->dx) - { - newLm->leftBound = e->prev; - newLm->rightBound = e; - } else - { - newLm->leftBound = e; - newLm->rightBound = e->prev; - } - newLm->leftBound->side = esLeft; - newLm->rightBound->side = esRight; - InsertLocalMinima( newLm ); - - for (;;) - { - if ( e->next->ytop == e->ytop && !NEAR_EQUAL(e->next->dx, HORIZONTAL) ) break; - e->nextInLML = e->next; - e = e->next; - if ( NEAR_EQUAL(e->dx, HORIZONTAL) && e->xbot != e->prev->xtop) SwapX(*e); - } - return e->next; -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPolygons(const Polygons &ppg, PolyType polyType) -{ - bool result = false; - for (Polygons::size_type i = 0; i < ppg.size(); ++i) - if (AddPolygon(ppg[i], polyType)) result = true; - return result; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Clear() -{ - DisposeLocalMinimaList(); - for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) delete [] m_edges[i]; - m_edges.clear(); - m_UseFullRange = false; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Reset() -{ - m_CurrentLM = m_MinimaList; - if( !m_CurrentLM ) return; //ie nothing to process - - //reset all edges ... - LocalMinima* lm = m_MinimaList; - while( lm ) - { - TEdge* e = lm->leftBound; - while( e ) - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - e->side = esLeft; - e->outIdx = -1; - e = e->nextInLML; - } - e = lm->rightBound; - while( e ) - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - e->side = esRight; - e->outIdx = -1; - e = e->nextInLML; - } - lm = lm->next; - } -} -//------------------------------------------------------------------------------ - -void ClipperBase::DisposeLocalMinimaList() -{ - while( m_MinimaList ) - { - LocalMinima* tmpLm = m_MinimaList->next; - delete m_MinimaList; - m_MinimaList = tmpLm; - } - m_CurrentLM = 0; -} -//------------------------------------------------------------------------------ - -void ClipperBase::PopLocalMinima() -{ - if( ! m_CurrentLM ) return; - m_CurrentLM = m_CurrentLM->next; -} -//------------------------------------------------------------------------------ - -IntRect ClipperBase::GetBounds() -{ - IntRect result; - LocalMinima* lm = m_MinimaList; - if (!lm) - { - result.left = result.top = result.right = result.bottom = 0; - return result; - } - result.left = lm->leftBound->xbot; - result.top = lm->leftBound->ybot; - result.right = lm->leftBound->xbot; - result.bottom = lm->leftBound->ybot; - while (lm) - { - if (lm->leftBound->ybot > result.bottom) - result.bottom = lm->leftBound->ybot; - TEdge* e = lm->leftBound; - for (;;) { - TEdge* bottomE = e; - while (e->nextInLML) - { - if (e->xbot < result.left) result.left = e->xbot; - if (e->xbot > result.right) result.right = e->xbot; - e = e->nextInLML; - } - if (e->xbot < result.left) result.left = e->xbot; - if (e->xbot > result.right) result.right = e->xbot; - if (e->xtop < result.left) result.left = e->xtop; - if (e->xtop > result.right) result.right = e->xtop; - if (e->ytop < result.top) result.top = e->ytop; - - if (bottomE == lm->leftBound) e = lm->rightBound; - else break; - } - lm = lm->next; - } - return result; -} - - -//------------------------------------------------------------------------------ -// TClipper methods ... -//------------------------------------------------------------------------------ - -Clipper::Clipper() : ClipperBase() //constructor -{ - m_Scanbeam = 0; - m_ActiveEdges = 0; - m_SortedEdges = 0; - m_IntersectNodes = 0; - m_ExecuteLocked = false; - m_UseFullRange = false; - m_ReverseOutput = false; -} -//------------------------------------------------------------------------------ - -Clipper::~Clipper() //destructor -{ - Clear(); - DisposeScanbeamList(); -} -//------------------------------------------------------------------------------ - -void Clipper::Clear() -{ - if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor - DisposeAllPolyPts(); - ClipperBase::Clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeScanbeamList() -{ - while ( m_Scanbeam ) { - Scanbeam* sb2 = m_Scanbeam->next; - delete m_Scanbeam; - m_Scanbeam = sb2; - } -} -//------------------------------------------------------------------------------ - -void Clipper::Reset() -{ - ClipperBase::Reset(); - m_Scanbeam = 0; - m_ActiveEdges = 0; - m_SortedEdges = 0; - DisposeAllPolyPts(); - LocalMinima* lm = m_MinimaList; - while (lm) - { - InsertScanbeam(lm->Y); - InsertScanbeam(lm->leftBound->ytop); - lm = lm->next; - } -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, Polygons &solution, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - if( m_ExecuteLocked ) return false; - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - bool succeeded = ExecuteInternal(false); - if (succeeded) BuildResult(solution); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, ExPolygons &solution, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - if( m_ExecuteLocked ) return false; - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - bool succeeded = ExecuteInternal(true); - if (succeeded) BuildResultEx(solution); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -bool PolySort(OutRec *or1, OutRec *or2) -{ - if (or1 == or2) return false; - if (!or1->pts || !or2->pts) - { - if (or1->pts != or2->pts) - { - return or1->pts ? true : false; - } - else return false; - } - int i1, i2; - if (or1->isHole) - i1 = or1->FirstLeft->idx; else - i1 = or1->idx; - if (or2->isHole) - i2 = or2->FirstLeft->idx; else - i2 = or2->idx; - int result = i1 - i2; - if (result == 0 && (or1->isHole != or2->isHole)) - { - return or1->isHole ? false : true; - } - else return result < 0; -} -//------------------------------------------------------------------------------ - -OutRec* FindAppendLinkEnd(OutRec *outRec) -{ - while (outRec->AppendLink) outRec = outRec->AppendLink; - return outRec; -} -//------------------------------------------------------------------------------ - -void Clipper::FixHoleLinkage(OutRec *outRec) -{ - OutRec *tmp; - if (outRec->bottomPt) - tmp = m_PolyOuts[outRec->bottomPt->idx]->FirstLeft; - else - tmp = outRec->FirstLeft; - if (outRec == tmp) throw clipperException("HoleLinkage error"); - - if (tmp) - { - if (tmp->AppendLink) tmp = FindAppendLinkEnd(tmp); - if (tmp == outRec) tmp = 0; - else if (tmp->isHole) - { - FixHoleLinkage(tmp); - tmp = tmp->FirstLeft; - } - } - outRec->FirstLeft = tmp; - if (!tmp) outRec->isHole = false; - outRec->AppendLink = 0; -} -//------------------------------------------------------------------------------ - -bool Clipper::ExecuteInternal(bool fixHoleLinkages) -{ - bool succeeded; - try { - Reset(); - if (!m_CurrentLM ) return true; - long64 botY = PopScanbeam(); - do { - InsertLocalMinimaIntoAEL(botY); - ClearHorzJoins(); - ProcessHorizontals(); - long64 topY = PopScanbeam(); - succeeded = ProcessIntersections(botY, topY); - if (!succeeded) break; - ProcessEdgesAtTopOfScanbeam(topY); - botY = topY; - } while( m_Scanbeam ); - } - catch(...) { - succeeded = false; - } - - if (succeeded) - { - //tidy up output polygons and fix orientations where necessary ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *outRec = m_PolyOuts[i]; - if (!outRec->pts) continue; - FixupOutPolygon(*outRec); - if (!outRec->pts) continue; - if (outRec->isHole && fixHoleLinkages) FixHoleLinkage(outRec); - - if (outRec->bottomPt == outRec->bottomFlag && - (Orientation(outRec, m_UseFullRange) != (Area(*outRec, m_UseFullRange) > 0))) - DisposeBottomPt(*outRec); - - if (outRec->isHole == - (m_ReverseOutput ^ Orientation(outRec, m_UseFullRange))) - ReversePolyPtLinks(*outRec->pts); - } - - JoinCommonEdges(fixHoleLinkages); - if (fixHoleLinkages) - std::sort(m_PolyOuts.begin(), m_PolyOuts.end(), PolySort); - } - - ClearJoins(); - ClearHorzJoins(); - return succeeded; -} -//------------------------------------------------------------------------------ - -void Clipper::InsertScanbeam(const long64 Y) -{ - if( !m_Scanbeam ) - { - m_Scanbeam = new Scanbeam; - m_Scanbeam->next = 0; - m_Scanbeam->Y = Y; - } - else if( Y > m_Scanbeam->Y ) - { - Scanbeam* newSb = new Scanbeam; - newSb->Y = Y; - newSb->next = m_Scanbeam; - m_Scanbeam = newSb; - } else - { - Scanbeam* sb2 = m_Scanbeam; - while( sb2->next && ( Y <= sb2->next->Y ) ) sb2 = sb2->next; - if( Y == sb2->Y ) return; //ie ignores duplicates - Scanbeam* newSb = new Scanbeam; - newSb->Y = Y; - newSb->next = sb2->next; - sb2->next = newSb; - } -} -//------------------------------------------------------------------------------ - -long64 Clipper::PopScanbeam() -{ - long64 Y = m_Scanbeam->Y; - Scanbeam* sb2 = m_Scanbeam; - m_Scanbeam = m_Scanbeam->next; - delete sb2; - return Y; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeAllPolyPts(){ - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - DisposeOutRec(i); - m_PolyOuts.clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeOutRec(PolyOutList::size_type index) -{ - OutRec *outRec = m_PolyOuts[index]; - if (outRec->pts) DisposeOutPts(outRec->pts); - delete outRec; - m_PolyOuts[index] = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::SetWindingCount(TEdge &edge) -{ - TEdge *e = edge.prevInAEL; - //find the edge of the same polytype that immediately preceeds 'edge' in AEL - while ( e && e->polyType != edge.polyType ) e = e->prevInAEL; - if ( !e ) - { - edge.windCnt = edge.windDelta; - edge.windCnt2 = 0; - e = m_ActiveEdges; //ie get ready to calc windCnt2 - } else if ( IsEvenOddFillType(edge) ) - { - //EvenOdd filling ... - edge.windCnt = 1; - edge.windCnt2 = e->windCnt2; - e = e->nextInAEL; //ie get ready to calc windCnt2 - } else - { - //nonZero, Positive or Negative filling ... - if ( e->windCnt * e->windDelta < 0 ) - { - if (Abs(e->windCnt) > 1) - { - if (e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; - else edge.windCnt = e->windCnt + edge.windDelta; - } else - edge.windCnt = e->windCnt + e->windDelta + edge.windDelta; - } else - { - if ( Abs(e->windCnt) > 1 && e->windDelta * edge.windDelta < 0) - edge.windCnt = e->windCnt; - else if ( e->windCnt + edge.windDelta == 0 ) - edge.windCnt = e->windCnt; - else edge.windCnt = e->windCnt + edge.windDelta; - } - edge.windCnt2 = e->windCnt2; - e = e->nextInAEL; //ie get ready to calc windCnt2 - } - - //update windCnt2 ... - if ( IsEvenOddAltFillType(edge) ) - { - //EvenOdd filling ... - while ( e != &edge ) - { - edge.windCnt2 = (edge.windCnt2 == 0) ? 1 : 0; - e = e->nextInAEL; - } - } else - { - //nonZero, Positive or Negative filling ... - while ( e != &edge ) - { - edge.windCnt2 += e->windDelta; - e = e->nextInAEL; - } - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddFillType(const TEdge& edge) const -{ - if (edge.polyType == ptSubject) - return m_SubjFillType == pftEvenOdd; else - return m_ClipFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const -{ - if (edge.polyType == ptSubject) - return m_ClipFillType == pftEvenOdd; else - return m_SubjFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsContributing(const TEdge& edge) const -{ - PolyFillType pft, pft2; - if (edge.polyType == ptSubject) - { - pft = m_SubjFillType; - pft2 = m_ClipFillType; - } else - { - pft = m_ClipFillType; - pft2 = m_SubjFillType; - } - - switch(pft) - { - case pftEvenOdd: - case pftNonZero: - if (Abs(edge.windCnt) != 1) return false; - break; - case pftPositive: - if (edge.windCnt != 1) return false; - break; - default: //pftNegative - if (edge.windCnt != -1) return false; - } - - switch(m_ClipType) - { - case ctIntersection: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 != 0); - case pftPositive: - return (edge.windCnt2 > 0); - default: - return (edge.windCnt2 < 0); - } - case ctUnion: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 == 0); - case pftPositive: - return (edge.windCnt2 <= 0); - default: - return (edge.windCnt2 >= 0); - } - case ctDifference: - if (edge.polyType == ptSubject) - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 == 0); - case pftPositive: - return (edge.windCnt2 <= 0); - default: - return (edge.windCnt2 >= 0); - } - else - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 != 0); - case pftPositive: - return (edge.windCnt2 > 0); - default: - return (edge.windCnt2 < 0); - } - default: - return true; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - TEdge *e, *prevE; - if( NEAR_EQUAL(e2->dx, HORIZONTAL) || ( e1->dx > e2->dx ) ) - { - AddOutPt( e1, pt ); - e2->outIdx = e1->outIdx; - e1->side = esLeft; - e2->side = esRight; - e = e1; - if (e->prevInAEL == e2) - prevE = e2->prevInAEL; - else - prevE = e->prevInAEL; - } else - { - AddOutPt( e2, pt ); - e1->outIdx = e2->outIdx; - e1->side = esRight; - e2->side = esLeft; - e = e2; - if (e->prevInAEL == e1) - prevE = e1->prevInAEL; - else - prevE = e->prevInAEL; - } - if (prevE && prevE->outIdx >= 0 && - (TopX(*prevE, pt.Y) == TopX(*e, pt.Y)) && - SlopesEqual(*e, *prevE, m_UseFullRange)) - AddJoin(e, prevE, -1, -1); -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - AddOutPt( e1, pt ); - if( e1->outIdx == e2->outIdx ) - { - e1->outIdx = -1; - e2->outIdx = -1; - } - else if (e1->outIdx < e2->outIdx) - AppendPolygon(e1, e2); - else - AppendPolygon(e2, e1); -} -//------------------------------------------------------------------------------ - -void Clipper::AddEdgeToSEL(TEdge *edge) -{ - //SEL pointers in PEdge are reused to build a list of horizontal edges. - //However, we don't need to worry about order with horizontal edge processing. - if( !m_SortedEdges ) - { - m_SortedEdges = edge; - edge->prevInSEL = 0; - edge->nextInSEL = 0; - } - else - { - edge->nextInSEL = m_SortedEdges; - edge->prevInSEL = 0; - m_SortedEdges->prevInSEL = edge; - m_SortedEdges = edge; - } -} -//------------------------------------------------------------------------------ - -void Clipper::CopyAELToSEL() -{ - TEdge* e = m_ActiveEdges; - m_SortedEdges = e; - if (!m_ActiveEdges) return; - m_SortedEdges->prevInSEL = 0; - e = e->nextInAEL; - while ( e ) - { - e->prevInSEL = e->prevInAEL; - e->prevInSEL->nextInSEL = e; - e->nextInSEL = 0; - e = e->nextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx, int e2OutIdx) -{ - JoinRec* jr = new JoinRec; - if (e1OutIdx >= 0) - jr->poly1Idx = e1OutIdx; else - jr->poly1Idx = e1->outIdx; - jr->pt1a = IntPoint(e1->xcurr, e1->ycurr); - jr->pt1b = IntPoint(e1->xtop, e1->ytop); - if (e2OutIdx >= 0) - jr->poly2Idx = e2OutIdx; else - jr->poly2Idx = e2->outIdx; - jr->pt2a = IntPoint(e2->xcurr, e2->ycurr); - jr->pt2b = IntPoint(e2->xtop, e2->ytop); - m_Joins.push_back(jr); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearJoins() -{ - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - delete m_Joins[i]; - m_Joins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::AddHorzJoin(TEdge *e, int idx) -{ - HorzJoinRec* hj = new HorzJoinRec; - hj->edge = e; - hj->savedIdx = idx; - m_HorizJoins.push_back(hj); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearHorzJoins() -{ - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); i++) - delete m_HorizJoins[i]; - m_HorizJoins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::InsertLocalMinimaIntoAEL( const long64 botY) -{ - while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) - { - TEdge* lb = m_CurrentLM->leftBound; - TEdge* rb = m_CurrentLM->rightBound; - - InsertEdgeIntoAEL( lb ); - InsertScanbeam( lb->ytop ); - InsertEdgeIntoAEL( rb ); - - if (IsEvenOddFillType(*lb)) - { - lb->windDelta = 1; - rb->windDelta = 1; - } - else - { - rb->windDelta = -lb->windDelta; - } - SetWindingCount( *lb ); - rb->windCnt = lb->windCnt; - rb->windCnt2 = lb->windCnt2; - - if( NEAR_EQUAL(rb->dx, HORIZONTAL) ) - { - //nb: only rightbounds can have a horizontal bottom edge - AddEdgeToSEL( rb ); - InsertScanbeam( rb->nextInLML->ytop ); - } - else - InsertScanbeam( rb->ytop ); - - if( IsContributing(*lb) ) - AddLocalMinPoly( lb, rb, IntPoint(lb->xcurr, m_CurrentLM->Y) ); - - //if any output polygons share an edge, they'll need joining later ... - if (rb->outIdx >= 0) - { - if (NEAR_EQUAL(rb->dx, HORIZONTAL)) - { - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - IntPoint pt, pt2; //returned by GetOverlapSegment() but unused here. - HorzJoinRec* hj = m_HorizJoins[i]; - //if horizontals rb and hj.edge overlap, flag for joining later ... - if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), - IntPoint(hj->edge->xtop, hj->edge->ytop), - IntPoint(rb->xbot, rb->ybot), - IntPoint(rb->xtop, rb->ytop), pt, pt2)) - AddJoin(hj->edge, rb, hj->savedIdx); - } - } - } - - if( lb->nextInAEL != rb ) - { - if (rb->outIdx >= 0 && rb->prevInAEL->outIdx >= 0 && - SlopesEqual(*rb->prevInAEL, *rb, m_UseFullRange)) - AddJoin(rb, rb->prevInAEL); - - TEdge* e = lb->nextInAEL; - IntPoint pt = IntPoint(lb->xcurr, lb->ycurr); - while( e != rb ) - { - if(!e) throw clipperException("InsertLocalMinimaIntoAEL: missing rightbound!"); - //nb: For calculating winding counts etc, IntersectEdges() assumes - //that param1 will be to the right of param2 ABOVE the intersection ... - IntersectEdges( rb , e , pt , ipNone); //order important here - e = e->nextInAEL; - } - } - PopLocalMinima(); - } -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromAEL(TEdge *e) -{ - TEdge* AelPrev = e->prevInAEL; - TEdge* AelNext = e->nextInAEL; - if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted - if( AelPrev ) AelPrev->nextInAEL = AelNext; - else m_ActiveEdges = AelNext; - if( AelNext ) AelNext->prevInAEL = AelPrev; - e->nextInAEL = 0; - e->prevInAEL = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromSEL(TEdge *e) -{ - TEdge* SelPrev = e->prevInSEL; - TEdge* SelNext = e->nextInSEL; - if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted - if( SelPrev ) SelPrev->nextInSEL = SelNext; - else m_SortedEdges = SelNext; - if( SelNext ) SelNext->prevInSEL = SelPrev; - e->nextInSEL = 0; - e->prevInSEL = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, - const IntPoint &pt, IntersectProtects protects) -{ - //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before - //e2 in AEL except when e1 is being inserted at the intersection point ... - bool e1stops = !(ipLeft & protects) && !e1->nextInLML && - e1->xtop == pt.X && e1->ytop == pt.Y; - bool e2stops = !(ipRight & protects) && !e2->nextInLML && - e2->xtop == pt.X && e2->ytop == pt.Y; - bool e1Contributing = ( e1->outIdx >= 0 ); - bool e2contributing = ( e2->outIdx >= 0 ); - - //update winding counts... - //assumes that e1 will be to the right of e2 ABOVE the intersection - if ( e1->polyType == e2->polyType ) - { - if ( IsEvenOddFillType( *e1) ) - { - int oldE1WindCnt = e1->windCnt; - e1->windCnt = e2->windCnt; - e2->windCnt = oldE1WindCnt; - } else - { - if (e1->windCnt + e2->windDelta == 0 ) e1->windCnt = -e1->windCnt; - else e1->windCnt += e2->windDelta; - if ( e2->windCnt - e1->windDelta == 0 ) e2->windCnt = -e2->windCnt; - else e2->windCnt -= e1->windDelta; - } - } else - { - if (!IsEvenOddFillType(*e2)) e1->windCnt2 += e2->windDelta; - else e1->windCnt2 = ( e1->windCnt2 == 0 ) ? 1 : 0; - if (!IsEvenOddFillType(*e1)) e2->windCnt2 -= e1->windDelta; - else e2->windCnt2 = ( e2->windCnt2 == 0 ) ? 1 : 0; - } - - PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; - if (e1->polyType == ptSubject) - { - e1FillType = m_SubjFillType; - e1FillType2 = m_ClipFillType; - } else - { - e1FillType = m_ClipFillType; - e1FillType2 = m_SubjFillType; - } - if (e2->polyType == ptSubject) - { - e2FillType = m_SubjFillType; - e2FillType2 = m_ClipFillType; - } else - { - e2FillType = m_ClipFillType; - e2FillType2 = m_SubjFillType; - } - - long64 e1Wc, e2Wc; - switch (e1FillType) - { - case pftPositive: e1Wc = e1->windCnt; break; - case pftNegative: e1Wc = -e1->windCnt; break; - default: e1Wc = Abs(e1->windCnt); - } - switch(e2FillType) - { - case pftPositive: e2Wc = e2->windCnt; break; - case pftNegative: e2Wc = -e2->windCnt; break; - default: e2Wc = Abs(e2->windCnt); - } - - if ( e1Contributing && e2contributing ) - { - if ( e1stops || e2stops || - (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || - (e1->polyType != e2->polyType && m_ClipType != ctXor) ) - AddLocalMaxPoly(e1, e2, pt); - else - DoBothEdges( e1, e2, pt ); - } - else if ( e1Contributing ) - { - if ((e2Wc == 0 || e2Wc == 1) && - (m_ClipType != ctIntersection || - e2->polyType == ptSubject || (e2->windCnt2 != 0))) - DoEdge1(e1, e2, pt); - } - else if ( e2contributing ) - { - if ((e1Wc == 0 || e1Wc == 1) && - (m_ClipType != ctIntersection || - e1->polyType == ptSubject || (e1->windCnt2 != 0))) - DoEdge2(e1, e2, pt); - } - else if ( (e1Wc == 0 || e1Wc == 1) && - (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) - { - //neither edge is currently contributing ... - - long64 e1Wc2, e2Wc2; - switch (e1FillType2) - { - case pftPositive: e1Wc2 = e1->windCnt2; break; - case pftNegative : e1Wc2 = -e1->windCnt2; break; - default: e1Wc2 = Abs(e1->windCnt2); - } - switch (e2FillType2) - { - case pftPositive: e2Wc2 = e2->windCnt2; break; - case pftNegative: e2Wc2 = -e2->windCnt2; break; - default: e2Wc2 = Abs(e2->windCnt2); - } - - if (e1->polyType != e2->polyType) - AddLocalMinPoly(e1, e2, pt); - else if (e1Wc == 1 && e2Wc == 1) - switch( m_ClipType ) { - case ctIntersection: - if (e1Wc2 > 0 && e2Wc2 > 0) - AddLocalMinPoly(e1, e2, pt); - break; - case ctUnion: - if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) - AddLocalMinPoly(e1, e2, pt); - break; - case ctDifference: - if (((e1->polyType == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || - ((e1->polyType == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) - AddLocalMinPoly(e1, e2, pt); - break; - case ctXor: - AddLocalMinPoly(e1, e2, pt); - } - else - SwapSides( *e1, *e2 ); - } - - if( (e1stops != e2stops) && - ( (e1stops && (e1->outIdx >= 0)) || (e2stops && (e2->outIdx >= 0)) ) ) - { - SwapSides( *e1, *e2 ); - SwapPolyIndexes( *e1, *e2 ); - } - - //finally, delete any non-contributing maxima edges ... - if( e1stops ) DeleteFromAEL( e1 ); - if( e2stops ) DeleteFromAEL( e2 ); -} -//------------------------------------------------------------------------------ - -void Clipper::SetHoleState(TEdge *e, OutRec *outRec) -{ - bool isHole = false; - TEdge *e2 = e->prevInAEL; - while (e2) - { - if (e2->outIdx >= 0) - { - isHole = !isHole; - if (! outRec->FirstLeft) - outRec->FirstLeft = m_PolyOuts[e2->outIdx]; - } - e2 = e2->prevInAEL; - } - if (isHole) outRec->isHole = true; -} -//------------------------------------------------------------------------------ - -OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) -{ - //work out which polygon fragment has the correct hole state ... - OutPt *outPt1 = outRec1->bottomPt; - OutPt *outPt2 = outRec2->bottomPt; - if (outPt1->pt.Y > outPt2->pt.Y) return outRec1; - else if (outPt1->pt.Y < outPt2->pt.Y) return outRec2; - else if (outPt1->pt.X < outPt2->pt.X) return outRec1; - else if (outPt1->pt.X > outPt2->pt.X) return outRec2; - else if (outPt1->next == outPt1) return outRec2; - else if (outPt2->next == outPt2) return outRec1; - else if (FirstIsBottomPt(outPt1, outPt2)) return outRec1; - else return outRec2; -} -//------------------------------------------------------------------------------ - -bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) -{ - do - { - outRec1 = outRec1->FirstLeft; - if (outRec1 == outRec2) return true; - } while (outRec1); - return false; -} -//------------------------------------------------------------------------------ - -void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) -{ - //get the start and ends of both output polygons ... - OutRec *outRec1 = m_PolyOuts[e1->outIdx]; - OutRec *outRec2 = m_PolyOuts[e2->outIdx]; - - OutRec *holeStateRec; - if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; - else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; - else holeStateRec = GetLowermostRec(outRec1, outRec2); - - OutPt* p1_lft = outRec1->pts; - OutPt* p1_rt = p1_lft->prev; - OutPt* p2_lft = outRec2->pts; - OutPt* p2_rt = p2_lft->prev; - - EdgeSide side; - //join e2 poly onto e1 poly and delete pointers to e2 ... - if( e1->side == esLeft ) - { - if( e2->side == esLeft ) - { - //z y x a b c - ReversePolyPtLinks(*p2_lft); - p2_lft->next = p1_lft; - p1_lft->prev = p2_lft; - p1_rt->next = p2_rt; - p2_rt->prev = p1_rt; - outRec1->pts = p2_rt; - } else - { - //x y z a b c - p2_rt->next = p1_lft; - p1_lft->prev = p2_rt; - p2_lft->prev = p1_rt; - p1_rt->next = p2_lft; - outRec1->pts = p2_lft; - } - side = esLeft; - } else - { - if( e2->side == esRight ) - { - //a b c z y x - ReversePolyPtLinks( *p2_lft ); - p1_rt->next = p2_rt; - p2_rt->prev = p1_rt; - p2_lft->next = p1_lft; - p1_lft->prev = p2_lft; - } else - { - //a b c x y z - p1_rt->next = p2_lft; - p2_lft->prev = p1_rt; - p1_lft->prev = p2_rt; - p2_rt->next = p1_lft; - } - side = esRight; - } - - if (holeStateRec == outRec2) - { - outRec1->bottomPt = outRec2->bottomPt; - outRec1->bottomPt->idx = outRec1->idx; - if (outRec2->FirstLeft != outRec1) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec1->isHole = outRec2->isHole; - } - outRec2->pts = 0; - outRec2->bottomPt = 0; - outRec2->AppendLink = outRec1; - int OKIdx = e1->outIdx; - int ObsoleteIdx = e2->outIdx; - - e1->outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly - e2->outIdx = -1; - - TEdge* e = m_ActiveEdges; - while( e ) - { - if( e->outIdx == ObsoleteIdx ) - { - e->outIdx = OKIdx; - e->side = side; - break; - } - e = e->nextInAEL; - } - - for (JoinList::size_type i = 0; i < m_Joins.size(); ++i) - { - if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx; - if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx; - } - - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - if (m_HorizJoins[i]->savedIdx == ObsoleteIdx) - m_HorizJoins[i]->savedIdx = OKIdx; - } - -} -//------------------------------------------------------------------------------ - -OutRec* Clipper::CreateOutRec() -{ - OutRec* result = new OutRec; - result->isHole = false; - result->FirstLeft = 0; - result->AppendLink = 0; - result->pts = 0; - result->bottomPt = 0; - result->sides = esNeither; - result->bottomFlag = 0; - - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeBottomPt(OutRec &outRec) -{ - OutPt* next = outRec.bottomPt->next; - OutPt* prev = outRec.bottomPt->prev; - if (outRec.pts == outRec.bottomPt) outRec.pts = next; - delete outRec.bottomPt; - next->prev = prev; - prev->next = next; - outRec.bottomPt = next; - FixupOutPolygon(outRec); -} -//------------------------------------------------------------------------------ - -void Clipper::AddOutPt(TEdge *e, const IntPoint &pt) -{ - bool ToFront = (e->side == esLeft); - if( e->outIdx < 0 ) - { - OutRec *outRec = CreateOutRec(); - m_PolyOuts.push_back(outRec); - outRec->idx = (int)m_PolyOuts.size()-1; - e->outIdx = outRec->idx; - OutPt* op = new OutPt; - outRec->pts = op; - outRec->bottomPt = op; - op->pt = pt; - op->idx = outRec->idx; - op->next = op; - op->prev = op; - SetHoleState(e, outRec); - } else - { - OutRec *outRec = m_PolyOuts[e->outIdx]; - OutPt* op = outRec->pts; - if ((ToFront && PointsEqual(pt, op->pt)) || - (!ToFront && PointsEqual(pt, op->prev->pt))) return; - - if ((e->side | outRec->sides) != outRec->sides) - { - //check for 'rounding' artefacts ... - if (outRec->sides == esNeither && pt.Y == op->pt.Y) - { - if (ToFront) - { - if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt - } - else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt - } - - outRec->sides = (EdgeSide)(outRec->sides | e->side); - if (outRec->sides == esBoth) - { - //A vertex from each side has now been added. - //Vertices of one side of an output polygon are quite commonly close to - //or even 'touching' edges of the other side of the output polygon. - //Very occasionally vertices from one side can 'cross' an edge on the - //the other side. The distance 'crossed' is always less that a unit - //and is purely an artefact of coordinate rounding. Nevertheless, this - //results in very tiny self-intersections. Because of the way - //orientation is calculated, even tiny self-intersections can cause - //the Orientation function to return the wrong result. Therefore, it's - //important to ensure that any self-intersections close to BottomPt are - //detected and removed before orientation is assigned. - - OutPt *opBot, *op2; - if (ToFront) - { - opBot = outRec->pts; - op2 = opBot->next; //op2 == right side - if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && - ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) < - (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) - outRec->bottomFlag = opBot; - } else - { - opBot = outRec->pts->prev; - op2 = opBot->prev; //op2 == left side - if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && - ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) > - (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) - outRec->bottomFlag = opBot; - } - } - } - - OutPt* op2 = new OutPt; - op2->pt = pt; - op2->idx = outRec->idx; - if (op2->pt.Y == outRec->bottomPt->pt.Y && - op2->pt.X < outRec->bottomPt->pt.X) - outRec->bottomPt = op2; - op2->next = op; - op2->prev = op->prev; - op2->prev->next = op2; - op->prev = op2; - if (ToFront) outRec->pts = op2; - } -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontals() -{ - TEdge* horzEdge = m_SortedEdges; - while( horzEdge ) - { - DeleteFromSEL( horzEdge ); - ProcessHorizontal( horzEdge ); - horzEdge = m_SortedEdges; - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsTopHorz(const long64 XPos) -{ - TEdge* e = m_SortedEdges; - while( e ) - { - if( ( XPos >= std::min(e->xcurr, e->xtop) ) && - ( XPos <= std::max(e->xcurr, e->xtop) ) ) return false; - e = e->nextInSEL; - } - return true; -} -//------------------------------------------------------------------------------ - -bool IsMinima(TEdge *e) -{ - return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e); -} -//------------------------------------------------------------------------------ - -bool IsMaxima(TEdge *e, const long64 Y) -{ - return e && e->ytop == Y && !e->nextInLML; -} -//------------------------------------------------------------------------------ - -bool IsIntermediate(TEdge *e, const long64 Y) -{ - return e->ytop == Y && e->nextInLML; -} -//------------------------------------------------------------------------------ - -TEdge *GetMaximaPair(TEdge *e) -{ - if( !IsMaxima(e->next, e->ytop) || e->next->xtop != e->xtop ) - return e->prev; else - return e->next; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInAEL(TEdge *edge1, TEdge *edge2) -{ - if( !edge1->nextInAEL && !edge1->prevInAEL ) return; - if( !edge2->nextInAEL && !edge2->prevInAEL ) return; - - if( edge1->nextInAEL == edge2 ) - { - TEdge* next = edge2->nextInAEL; - if( next ) next->prevInAEL = edge1; - TEdge* prev = edge1->prevInAEL; - if( prev ) prev->nextInAEL = edge2; - edge2->prevInAEL = prev; - edge2->nextInAEL = edge1; - edge1->prevInAEL = edge2; - edge1->nextInAEL = next; - } - else if( edge2->nextInAEL == edge1 ) - { - TEdge* next = edge1->nextInAEL; - if( next ) next->prevInAEL = edge2; - TEdge* prev = edge2->prevInAEL; - if( prev ) prev->nextInAEL = edge1; - edge1->prevInAEL = prev; - edge1->nextInAEL = edge2; - edge2->prevInAEL = edge1; - edge2->nextInAEL = next; - } - else - { - TEdge* next = edge1->nextInAEL; - TEdge* prev = edge1->prevInAEL; - edge1->nextInAEL = edge2->nextInAEL; - if( edge1->nextInAEL ) edge1->nextInAEL->prevInAEL = edge1; - edge1->prevInAEL = edge2->prevInAEL; - if( edge1->prevInAEL ) edge1->prevInAEL->nextInAEL = edge1; - edge2->nextInAEL = next; - if( edge2->nextInAEL ) edge2->nextInAEL->prevInAEL = edge2; - edge2->prevInAEL = prev; - if( edge2->prevInAEL ) edge2->prevInAEL->nextInAEL = edge2; - } - - if( !edge1->prevInAEL ) m_ActiveEdges = edge1; - else if( !edge2->prevInAEL ) m_ActiveEdges = edge2; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) -{ - if( !( edge1->nextInSEL ) && !( edge1->prevInSEL ) ) return; - if( !( edge2->nextInSEL ) && !( edge2->prevInSEL ) ) return; - - if( edge1->nextInSEL == edge2 ) - { - TEdge* next = edge2->nextInSEL; - if( next ) next->prevInSEL = edge1; - TEdge* prev = edge1->prevInSEL; - if( prev ) prev->nextInSEL = edge2; - edge2->prevInSEL = prev; - edge2->nextInSEL = edge1; - edge1->prevInSEL = edge2; - edge1->nextInSEL = next; - } - else if( edge2->nextInSEL == edge1 ) - { - TEdge* next = edge1->nextInSEL; - if( next ) next->prevInSEL = edge2; - TEdge* prev = edge2->prevInSEL; - if( prev ) prev->nextInSEL = edge1; - edge1->prevInSEL = prev; - edge1->nextInSEL = edge2; - edge2->prevInSEL = edge1; - edge2->nextInSEL = next; - } - else - { - TEdge* next = edge1->nextInSEL; - TEdge* prev = edge1->prevInSEL; - edge1->nextInSEL = edge2->nextInSEL; - if( edge1->nextInSEL ) edge1->nextInSEL->prevInSEL = edge1; - edge1->prevInSEL = edge2->prevInSEL; - if( edge1->prevInSEL ) edge1->prevInSEL->nextInSEL = edge1; - edge2->nextInSEL = next; - if( edge2->nextInSEL ) edge2->nextInSEL->prevInSEL = edge2; - edge2->prevInSEL = prev; - if( edge2->prevInSEL ) edge2->prevInSEL->nextInSEL = edge2; - } - - if( !edge1->prevInSEL ) m_SortedEdges = edge1; - else if( !edge2->prevInSEL ) m_SortedEdges = edge2; -} -//------------------------------------------------------------------------------ - -TEdge* GetNextInAEL(TEdge *e, Direction dir) -{ - return dir == dLeftToRight ? e->nextInAEL : e->prevInAEL; -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontal(TEdge *horzEdge) -{ - Direction dir; - long64 horzLeft, horzRight; - - if( horzEdge->xcurr < horzEdge->xtop ) - { - horzLeft = horzEdge->xcurr; - horzRight = horzEdge->xtop; - dir = dLeftToRight; - } else - { - horzLeft = horzEdge->xtop; - horzRight = horzEdge->xcurr; - dir = dRightToLeft; - } - - TEdge* eMaxPair; - if( horzEdge->nextInLML ) eMaxPair = 0; - else eMaxPair = GetMaximaPair(horzEdge); - - TEdge* e = GetNextInAEL( horzEdge , dir ); - while( e ) - { - TEdge* eNext = GetNextInAEL( e, dir ); - - if (eMaxPair || - ((dir == dLeftToRight) && (e->xcurr <= horzRight)) || - ((dir == dRightToLeft) && (e->xcurr >= horzLeft))) - { - //ok, so far it looks like we're still in range of the horizontal edge - if ( e->xcurr == horzEdge->xtop && !eMaxPair ) - { - if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) - { - //if output polygons share an edge, they'll need joining later ... - if (horzEdge->outIdx >= 0 && e->outIdx >= 0) - AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx); - break; //we've reached the end of the horizontal line - } - else if (e->dx < horzEdge->nextInLML->dx) - //we really have got to the end of the intermediate horz edge so quit. - //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal. - break; - } - - if( e == eMaxPair ) - { - //horzEdge is evidently a maxima horizontal and we've arrived at its end. - if (dir == dLeftToRight) - IntersectEdges(horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); - else - IntersectEdges(e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); - if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); - return; - } - else if( NEAR_EQUAL(e->dx, HORIZONTAL) && !IsMinima(e) && !(e->xcurr > e->xtop) ) - { - //An overlapping horizontal edge. Overlapping horizontal edges are - //processed as if layered with the current horizontal edge (horizEdge) - //being infinitesimally lower that the next (e). Therfore, we - //intersect with e only if e.xcurr is within the bounds of horzEdge ... - if( dir == dLeftToRight ) - IntersectEdges( horzEdge , e, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); - else - IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); - } - else if( dir == dLeftToRight ) - { - IntersectEdges( horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); - } - else - { - IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); - } - SwapPositionsInAEL( horzEdge, e ); - } - else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) || - (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break; - e = eNext; - } //end while - - if( horzEdge->nextInLML ) - { - if( horzEdge->outIdx >= 0 ) - AddOutPt( horzEdge, IntPoint(horzEdge->xtop, horzEdge->ytop)); - UpdateEdgeIntoAEL( horzEdge ); - } - else - { - if ( horzEdge->outIdx >= 0 ) - IntersectEdges( horzEdge, eMaxPair, - IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); - if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); - DeleteFromAEL(eMaxPair); - DeleteFromAEL(horzEdge); - } -} -//------------------------------------------------------------------------------ - -void Clipper::UpdateEdgeIntoAEL(TEdge *&e) -{ - if( !e->nextInLML ) throw - clipperException("UpdateEdgeIntoAEL: invalid call"); - TEdge* AelPrev = e->prevInAEL; - TEdge* AelNext = e->nextInAEL; - e->nextInLML->outIdx = e->outIdx; - if( AelPrev ) AelPrev->nextInAEL = e->nextInLML; - else m_ActiveEdges = e->nextInLML; - if( AelNext ) AelNext->prevInAEL = e->nextInLML; - e->nextInLML->side = e->side; - e->nextInLML->windDelta = e->windDelta; - e->nextInLML->windCnt = e->windCnt; - e->nextInLML->windCnt2 = e->windCnt2; - e = e->nextInLML; - e->prevInAEL = AelPrev; - e->nextInAEL = AelNext; - if( !NEAR_EQUAL(e->dx, HORIZONTAL) ) InsertScanbeam( e->ytop ); -} -//------------------------------------------------------------------------------ - -bool Clipper::ProcessIntersections(const long64 botY, const long64 topY) -{ - if( !m_ActiveEdges ) return true; - try { - BuildIntersectList(botY, topY); - if ( !m_IntersectNodes) return true; - if ( FixupIntersections() ) ProcessIntersectList(); - else return false; - } - catch(...) { - m_SortedEdges = 0; - DisposeIntersectNodes(); - throw clipperException("ProcessIntersections error"); - } - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeIntersectNodes() -{ - while ( m_IntersectNodes ) - { - IntersectNode* iNode = m_IntersectNodes->next; - delete m_IntersectNodes; - m_IntersectNodes = iNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildIntersectList(const long64 botY, const long64 topY) -{ - if ( !m_ActiveEdges ) return; - - //prepare for sorting ... - TEdge* e = m_ActiveEdges; - e->tmpX = TopX( *e, topY ); - m_SortedEdges = e; - m_SortedEdges->prevInSEL = 0; - e = e->nextInAEL; - while( e ) - { - e->prevInSEL = e->prevInAEL; - e->prevInSEL->nextInSEL = e; - e->nextInSEL = 0; - e->tmpX = TopX( *e, topY ); - e = e->nextInAEL; - } - - //bubblesort ... - bool isModified = true; - while( isModified && m_SortedEdges ) - { - isModified = false; - e = m_SortedEdges; - while( e->nextInSEL ) - { - TEdge *eNext = e->nextInSEL; - IntPoint pt; - if(e->tmpX > eNext->tmpX && - IntersectPoint(*e, *eNext, pt, m_UseFullRange)) - { - if (pt.Y > botY) - { - pt.Y = botY; - pt.X = TopX(*e, pt.Y); - } - AddIntersectNode( e, eNext, pt ); - SwapPositionsInSEL(e, eNext); - isModified = true; - } - else - e = eNext; - } - if( e->prevInSEL ) e->prevInSEL->nextInSEL = 0; - else break; - } - m_SortedEdges = 0; -} -//------------------------------------------------------------------------------ - -bool ProcessParam1BeforeParam2(IntersectNode &node1, IntersectNode &node2) -{ - bool result; - if (node1.pt.Y == node2.pt.Y) - { - if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) - { - result = node2.pt.X > node1.pt.X; - return node2.edge1->dx > 0 ? !result : result; - } - else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) - { - result = node2.pt.X > node1.pt.X; - return node2.edge2->dx > 0 ? !result : result; - } - else return node2.pt.X > node1.pt.X; - } - else return node1.pt.Y > node2.pt.Y; -} -//------------------------------------------------------------------------------ - -void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - IntersectNode* newNode = new IntersectNode; - newNode->edge1 = e1; - newNode->edge2 = e2; - newNode->pt = pt; - newNode->next = 0; - if( !m_IntersectNodes ) m_IntersectNodes = newNode; - else if( ProcessParam1BeforeParam2(*newNode, *m_IntersectNodes) ) - { - newNode->next = m_IntersectNodes; - m_IntersectNodes = newNode; - } - else - { - IntersectNode* iNode = m_IntersectNodes; - while( iNode->next && ProcessParam1BeforeParam2(*iNode->next, *newNode) ) - iNode = iNode->next; - newNode->next = iNode->next; - iNode->next = newNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessIntersectList() -{ - while( m_IntersectNodes ) - { - IntersectNode* iNode = m_IntersectNodes->next; - { - IntersectEdges( m_IntersectNodes->edge1 , - m_IntersectNodes->edge2 , m_IntersectNodes->pt, ipBoth ); - SwapPositionsInAEL( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 ); - } - delete m_IntersectNodes; - m_IntersectNodes = iNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::DoMaxima(TEdge *e, long64 topY) -{ - TEdge* eMaxPair = GetMaximaPair(e); - long64 X = e->xtop; - TEdge* eNext = e->nextInAEL; - while( eNext != eMaxPair ) - { - if (!eNext) throw clipperException("DoMaxima error"); - IntersectEdges( e, eNext, IntPoint(X, topY), ipBoth ); - eNext = eNext->nextInAEL; - } - if( e->outIdx < 0 && eMaxPair->outIdx < 0 ) - { - DeleteFromAEL( e ); - DeleteFromAEL( eMaxPair ); - } - else if( e->outIdx >= 0 && eMaxPair->outIdx >= 0 ) - { - IntersectEdges( e, eMaxPair, IntPoint(X, topY), ipNone ); - } - else throw clipperException("DoMaxima error"); -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY) -{ - TEdge* e = m_ActiveEdges; - while( e ) - { - //1. process maxima, treating them as if they're 'bent' horizontal edges, - // but exclude maxima with horizontal edges. nb: e can't be a horizontal. - if( IsMaxima(e, topY) && !NEAR_EQUAL(GetMaximaPair(e)->dx, HORIZONTAL) ) - { - //'e' might be removed from AEL, as may any following edges so ... - TEdge* ePrior = e->prevInAEL; - DoMaxima(e, topY); - if( !ePrior ) e = m_ActiveEdges; - else e = ePrior->nextInAEL; - } - else - { - //2. promote horizontal edges, otherwise update xcurr and ycurr ... - if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) ) - { - if (e->outIdx >= 0) - { - AddOutPt(e, IntPoint(e->xtop, e->ytop)); - - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - IntPoint pt, pt2; - HorzJoinRec* hj = m_HorizJoins[i]; - if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), - IntPoint(hj->edge->xtop, hj->edge->ytop), - IntPoint(e->nextInLML->xbot, e->nextInLML->ybot), - IntPoint(e->nextInLML->xtop, e->nextInLML->ytop), pt, pt2)) - AddJoin(hj->edge, e->nextInLML, hj->savedIdx, e->outIdx); - } - - AddHorzJoin(e->nextInLML, e->outIdx); - } - UpdateEdgeIntoAEL(e); - AddEdgeToSEL(e); - } else - { - //this just simplifies horizontal processing ... - e->xcurr = TopX( *e, topY ); - e->ycurr = topY; - } - e = e->nextInAEL; - } - } - - //3. Process horizontals at the top of the scanbeam ... - ProcessHorizontals(); - - //4. Promote intermediate vertices ... - e = m_ActiveEdges; - while( e ) - { - if( IsIntermediate( e, topY ) ) - { - if( e->outIdx >= 0 ) AddOutPt(e, IntPoint(e->xtop,e->ytop)); - UpdateEdgeIntoAEL(e); - - //if output polygons share an edge, they'll need joining later ... - if (e->outIdx >= 0 && e->prevInAEL && e->prevInAEL->outIdx >= 0 && - e->prevInAEL->xcurr == e->xbot && e->prevInAEL->ycurr == e->ybot && - SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), - IntPoint(e->xbot,e->ybot), - IntPoint(e->prevInAEL->xtop, e->prevInAEL->ytop), m_UseFullRange)) - { - AddOutPt(e->prevInAEL, IntPoint(e->xbot, e->ybot)); - AddJoin(e, e->prevInAEL); - } - else if (e->outIdx >= 0 && e->nextInAEL && e->nextInAEL->outIdx >= 0 && - e->nextInAEL->ycurr > e->nextInAEL->ytop && - e->nextInAEL->ycurr <= e->nextInAEL->ybot && - e->nextInAEL->xcurr == e->xbot && e->nextInAEL->ycurr == e->ybot && - SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), - IntPoint(e->xbot,e->ybot), - IntPoint(e->nextInAEL->xtop, e->nextInAEL->ytop), m_UseFullRange)) - { - AddOutPt(e->nextInAEL, IntPoint(e->xbot, e->ybot)); - AddJoin(e, e->nextInAEL); - } - } - e = e->nextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::FixupOutPolygon(OutRec &outRec) -{ - //FixupOutPolygon() - removes duplicate points and simplifies consecutive - //parallel edges by removing the middle vertex. - OutPt *lastOK = 0; - outRec.pts = outRec.bottomPt; - OutPt *pp = outRec.bottomPt; - - for (;;) - { - if (pp->prev == pp || pp->prev == pp->next ) - { - DisposeOutPts(pp); - outRec.pts = 0; - outRec.bottomPt = 0; - return; - } - //test for duplicate points and for same slope (cross-product) ... - if ( PointsEqual(pp->pt, pp->next->pt) || - SlopesEqual(pp->prev->pt, pp->pt, pp->next->pt, m_UseFullRange) ) - { - lastOK = 0; - OutPt *tmp = pp; - if (pp == outRec.bottomPt) - outRec.bottomPt = 0; //flags need for updating - pp->prev->next = pp->next; - pp->next->prev = pp->prev; - pp = pp->prev; - delete tmp; - } - else if (pp == lastOK) break; - else - { - if (!lastOK) lastOK = pp; - pp = pp->next; - } - } - if (!outRec.bottomPt) { - outRec.bottomPt = GetBottomPt(pp); - outRec.bottomPt->idx = outRec.idx; - outRec.pts = outRec.bottomPt; - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResult(Polygons &polys) -{ - int k = 0; - polys.resize(m_PolyOuts.size()); - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - if (m_PolyOuts[i]->pts) - { - Polygon* pg = &polys[k]; - pg->clear(); - OutPt* p = m_PolyOuts[i]->pts; - do - { - pg->push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - //make sure each polygon has at least 3 vertices ... - if (pg->size() < 3) pg->clear(); else k++; - } - } - polys.resize(k); -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResultEx(ExPolygons &polys) -{ - PolyOutList::size_type i = 0; - int k = 0; - polys.resize(0); - polys.reserve(m_PolyOuts.size()); - while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts) - { - ExPolygon epg; - OutPt* p = m_PolyOuts[i]->pts; - do { - epg.outer.push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - i++; - //make sure polygons have at least 3 vertices ... - if (epg.outer.size() < 3) continue; - while (i < m_PolyOuts.size() - && m_PolyOuts[i]->pts && m_PolyOuts[i]->isHole) - { - Polygon pg; - p = m_PolyOuts[i]->pts; - do { - pg.push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - epg.holes.push_back(pg); - i++; - } - polys.push_back(epg); - k++; - } - polys.resize(k); -} -//------------------------------------------------------------------------------ - -void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) -{ - TEdge *e1 = int1.edge1; - TEdge *e2 = int1.edge2; - IntPoint p = int1.pt; - - int1.edge1 = int2.edge1; - int1.edge2 = int2.edge2; - int1.pt = int2.pt; - - int2.edge1 = e1; - int2.edge2 = e2; - int2.pt = p; -} -//------------------------------------------------------------------------------ - -bool Clipper::FixupIntersections() -{ - if ( !m_IntersectNodes->next ) return true; - - CopyAELToSEL(); - IntersectNode *int1 = m_IntersectNodes; - IntersectNode *int2 = m_IntersectNodes->next; - while (int2) - { - TEdge *e1 = int1->edge1; - TEdge *e2; - if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL; - else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL; - else - { - //The current intersection is out of order, so try and swap it with - //a subsequent intersection ... - while (int2) - { - if (int2->edge1->nextInSEL == int2->edge2 || - int2->edge1->prevInSEL == int2->edge2) break; - else int2 = int2->next; - } - if ( !int2 ) return false; //oops!!! - - //found an intersect node that can be swapped ... - SwapIntersectNodes(*int1, *int2); - e1 = int1->edge1; - e2 = int1->edge2; - } - SwapPositionsInSEL(e1, e2); - int1 = int1->next; - int2 = int1->next; - } - - m_SortedEdges = 0; - - //finally, check the last intersection too ... - return (int1->edge1->prevInSEL == int1->edge2 || - int1->edge1->nextInSEL == int1->edge2); -} -//------------------------------------------------------------------------------ - -bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) -{ - return e2.xcurr == e1.xcurr ? e2.dx > e1.dx : e2.xcurr < e1.xcurr; -} -//------------------------------------------------------------------------------ - -void Clipper::InsertEdgeIntoAEL(TEdge *edge) -{ - edge->prevInAEL = 0; - edge->nextInAEL = 0; - if( !m_ActiveEdges ) - { - m_ActiveEdges = edge; - } - else if( E2InsertsBeforeE1(*m_ActiveEdges, *edge) ) - { - edge->nextInAEL = m_ActiveEdges; - m_ActiveEdges->prevInAEL = edge; - m_ActiveEdges = edge; - } else - { - TEdge* e = m_ActiveEdges; - while( e->nextInAEL && !E2InsertsBeforeE1(*e->nextInAEL , *edge) ) - e = e->nextInAEL; - edge->nextInAEL = e->nextInAEL; - if( e->nextInAEL ) e->nextInAEL->prevInAEL = edge; - edge->prevInAEL = e; - e->nextInAEL = edge; - } -} -//---------------------------------------------------------------------- - -void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge1, pt); - SwapSides(*edge1, *edge2); - SwapPolyIndexes(*edge1, *edge2); -} -//---------------------------------------------------------------------- - -void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge2, pt); - SwapSides(*edge1, *edge2); - SwapPolyIndexes(*edge1, *edge2); -} -//---------------------------------------------------------------------- - -void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge1, pt); - AddOutPt(edge2, pt); - SwapSides( *edge1 , *edge2 ); - SwapPolyIndexes( *edge1 , *edge2 ); -} -//---------------------------------------------------------------------- - -void Clipper::CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2) -{ - //when a polygon is split into 2 polygons, make sure any holes the original - //polygon contained link to the correct polygon ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *orec = m_PolyOuts[i]; - if (orec->isHole && orec->bottomPt && orec->FirstLeft == outRec1 && - !PointInPolygon(orec->bottomPt->pt, outRec1->pts, m_UseFullRange)) - orec->FirstLeft = outRec2; - } -} -//---------------------------------------------------------------------- - -void Clipper::CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2) -{ - //if a hole is owned by outRec2 then make it owned by outRec1 ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - if (m_PolyOuts[i]->isHole && m_PolyOuts[i]->bottomPt && - m_PolyOuts[i]->FirstLeft == outRec2) - m_PolyOuts[i]->FirstLeft = outRec1; -} -//---------------------------------------------------------------------- - -void Clipper::JoinCommonEdges(bool fixHoleLinkages) -{ - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - { - JoinRec* j = m_Joins[i]; - OutRec *outRec1 = m_PolyOuts[j->poly1Idx]; - OutPt *pp1a = outRec1->pts; - OutRec *outRec2 = m_PolyOuts[j->poly2Idx]; - OutPt *pp2a = outRec2->pts; - IntPoint pt1 = j->pt2a, pt2 = j->pt2b; - IntPoint pt3 = j->pt1a, pt4 = j->pt1b; - if (!FindSegment(pp1a, pt1, pt2)) continue; - if (j->poly1Idx == j->poly2Idx) - { - //we're searching the same polygon for overlapping segments so - //segment 2 mustn't be the same as segment 1 ... - pp2a = pp1a->next; - if (!FindSegment(pp2a, pt3, pt4) || (pp2a == pp1a)) continue; - } - else if (!FindSegment(pp2a, pt3, pt4)) continue; - - if (!GetOverlapSegment(pt1, pt2, pt3, pt4, pt1, pt2)) continue; - - OutPt *p1, *p2, *p3, *p4; - OutPt *prev = pp1a->prev; - //get p1 & p2 polypts - the overlap start & endpoints on poly1 - if (PointsEqual(pp1a->pt, pt1)) p1 = pp1a; - else if (PointsEqual(prev->pt, pt1)) p1 = prev; - else p1 = InsertPolyPtBetween(pp1a, prev, pt1); - - if (PointsEqual(pp1a->pt, pt2)) p2 = pp1a; - else if (PointsEqual(prev->pt, pt2)) p2 = prev; - else if ((p1 == pp1a) || (p1 == prev)) - p2 = InsertPolyPtBetween(pp1a, prev, pt2); - else if (Pt3IsBetweenPt1AndPt2(pp1a->pt, p1->pt, pt2)) - p2 = InsertPolyPtBetween(pp1a, p1, pt2); else - p2 = InsertPolyPtBetween(p1, prev, pt2); - - //get p3 & p4 polypts - the overlap start & endpoints on poly2 - prev = pp2a->prev; - if (PointsEqual(pp2a->pt, pt1)) p3 = pp2a; - else if (PointsEqual(prev->pt, pt1)) p3 = prev; - else p3 = InsertPolyPtBetween(pp2a, prev, pt1); - - if (PointsEqual(pp2a->pt, pt2)) p4 = pp2a; - else if (PointsEqual(prev->pt, pt2)) p4 = prev; - else if ((p3 == pp2a) || (p3 == prev)) - p4 = InsertPolyPtBetween(pp2a, prev, pt2); - else if (Pt3IsBetweenPt1AndPt2(pp2a->pt, p3->pt, pt2)) - p4 = InsertPolyPtBetween(pp2a, p3, pt2); else - p4 = InsertPolyPtBetween(p3, prev, pt2); - - //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... - if (p1->next == p2 && p3->prev == p4) - { - p1->next = p3; - p3->prev = p1; - p2->prev = p4; - p4->next = p2; - } - else if (p1->prev == p2 && p3->next == p4) - { - p1->prev = p3; - p3->next = p1; - p2->next = p4; - p4->prev = p2; - } - else - continue; //an orientation is probably wrong - - if (j->poly2Idx == j->poly1Idx) - { - //instead of joining two polygons, we've just created a new one by - //splitting one polygon into two. - outRec1->pts = GetBottomPt(p1); - outRec1->bottomPt = outRec1->pts; - outRec1->bottomPt->idx = outRec1->idx; - outRec2 = CreateOutRec(); - m_PolyOuts.push_back(outRec2); - outRec2->idx = (int)m_PolyOuts.size()-1; - j->poly2Idx = outRec2->idx; - outRec2->pts = GetBottomPt(p2); - outRec2->bottomPt = outRec2->pts; - outRec2->bottomPt->idx = outRec2->idx; - - if (PointInPolygon(outRec2->pts->pt, outRec1->pts, m_UseFullRange)) - { - //outRec2 is contained by outRec1 ... - outRec2->isHole = !outRec1->isHole; - outRec2->FirstLeft = outRec1; - if (outRec2->isHole == - (m_ReverseOutput ^ Orientation(outRec2, m_UseFullRange))) - ReversePolyPtLinks(*outRec2->pts); - } else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange)) - { - //outRec1 is contained by outRec2 ... - outRec2->isHole = outRec1->isHole; - outRec1->isHole = !outRec2->isHole; - outRec2->FirstLeft = outRec1->FirstLeft; - outRec1->FirstLeft = outRec2; - if (outRec1->isHole == - (m_ReverseOutput ^ Orientation(outRec1, m_UseFullRange))) - ReversePolyPtLinks(*outRec1->pts); - //make sure any contained holes now link to the correct polygon ... - if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); - } else - { - outRec2->isHole = outRec1->isHole; - outRec2->FirstLeft = outRec1->FirstLeft; - //make sure any contained holes now link to the correct polygon ... - if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); - } - - //now fixup any subsequent joins that match this polygon - for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) - { - JoinRec* j2 = m_Joins[k]; - if (j2->poly1Idx == j->poly1Idx && PointIsVertex(j2->pt1a, p2)) - j2->poly1Idx = j->poly2Idx; - if (j2->poly2Idx == j->poly1Idx && PointIsVertex(j2->pt2a, p2)) - j2->poly2Idx = j->poly2Idx; - } - - //now cleanup redundant edges too ... - FixupOutPolygon(*outRec1); - FixupOutPolygon(*outRec2); - - if (Orientation(outRec1, m_UseFullRange) != (Area(*outRec1, m_UseFullRange) > 0)) - DisposeBottomPt(*outRec1); - if (Orientation(outRec2, m_UseFullRange) != (Area(*outRec2, m_UseFullRange) > 0)) - DisposeBottomPt(*outRec2); - - } else - { - //joined 2 polygons together ... - - //make sure any holes contained by outRec2 now link to outRec1 ... - if (fixHoleLinkages) CheckHoleLinkages2(outRec1, outRec2); - - //now cleanup redundant edges too ... - FixupOutPolygon(*outRec1); - - if (outRec1->pts) - { - outRec1->isHole = !Orientation(outRec1, m_UseFullRange); - if (outRec1->isHole && !outRec1->FirstLeft) - outRec1->FirstLeft = outRec2->FirstLeft; - } - - //delete the obsolete pointer ... - int OKIdx = outRec1->idx; - int ObsoleteIdx = outRec2->idx; - outRec2->pts = 0; - outRec2->bottomPt = 0; - outRec2->AppendLink = outRec1; - - //now fixup any subsequent Joins that match this polygon - for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) - { - JoinRec* j2 = m_Joins[k]; - if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx; - if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx; - } - } - } -} -//------------------------------------------------------------------------------ - -void ReversePolygon(Polygon& p) -{ - std::reverse(p.begin(), p.end()); -} -//------------------------------------------------------------------------------ - -void ReversePolygons(Polygons& p) -{ - for (Polygons::size_type i = 0; i < p.size(); ++i) - ReversePolygon(p[i]); -} - -//------------------------------------------------------------------------------ -// OffsetPolygon functions ... -//------------------------------------------------------------------------------ - -struct DoublePoint -{ - double X; - double Y; - DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} -}; -//------------------------------------------------------------------------------ - -Polygon BuildArc(const IntPoint &pt, - const double a1, const double a2, const double r) -{ - long64 steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1))); - if (steps > 0x100000) steps = 0x100000; - int n = (unsigned)steps; - Polygon result(n); - double da = (a2 - a1) / (n -1); - double a = a1; - for (int i = 0; i < n; ++i) - { - result[i].X = pt.X + Round(std::cos(a)*r); - result[i].Y = pt.Y + Round(std::sin(a)*r); - a += da; - } - return result; -} -//------------------------------------------------------------------------------ - -DoublePoint GetUnitNormal( const IntPoint &pt1, const IntPoint &pt2) -{ - if(pt2.X == pt1.X && pt2.Y == pt1.Y) - return DoublePoint(0, 0); - - double dx = (double)(pt2.X - pt1.X); - double dy = (double)(pt2.Y - pt1.Y); - double f = 1 *1.0/ std::sqrt( dx*dx + dy*dy ); - dx *= f; - dy *= f; - return DoublePoint(dy, -dx); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -class PolyOffsetBuilder -{ -private: - Polygons m_p; - Polygon* m_curr_poly; - std::vector normals; - double m_delta, m_RMin, m_R; - size_t m_i, m_j, m_k; - static const int buffLength = 128; - JoinType m_jointype; - -public: - -PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys, - double delta, JoinType jointype, double MiterLimit) -{ - //nb precondition - out_polys != ptsin_polys - if (NEAR_ZERO(delta)) - { - out_polys = in_polys; - return; - } - - this->m_p = in_polys; - this->m_delta = delta; - this->m_jointype = jointype; - if (MiterLimit <= 1) MiterLimit = 1; - m_RMin = 2/(MiterLimit*MiterLimit); - - double deltaSq = delta*delta; - out_polys.clear(); - out_polys.resize(in_polys.size()); - for (m_i = 0; m_i < in_polys.size(); m_i++) - { - m_curr_poly = &out_polys[m_i]; - size_t len = in_polys[m_i].size(); - if (len > 1 && m_p[m_i][0].X == m_p[m_i][len - 1].X && - m_p[m_i][0].Y == m_p[m_i][len-1].Y) len--; - - //when 'shrinking' polygons - to minimize artefacts - //strip those polygons that have an area < pi * delta^2 ... - double a1 = Area(in_polys[m_i]); - if (delta < 0) { if (a1 > 0 && a1 < deltaSq *pi) len = 0; } - else if (a1 < 0 && -a1 < deltaSq *pi) len = 0; //holes have neg. area - - if (len == 0 || (len < 3 && delta <= 0)) - continue; - else if (len == 1) - { - Polygon arc; - arc = BuildArc(in_polys[m_i][len-1], 0, 2 * pi, delta); - out_polys[m_i] = arc; - continue; - } - - //build normals ... - normals.clear(); - normals.resize(len); - normals[len-1] = GetUnitNormal(in_polys[m_i][len-1], in_polys[m_i][0]); - for (m_j = 0; m_j < len -1; ++m_j) - normals[m_j] = GetUnitNormal(in_polys[m_i][m_j], in_polys[m_i][m_j+1]); - - m_k = len -1; - for (m_j = 0; m_j < len; ++m_j) - { - switch (jointype) - { - case jtMiter: - { - m_R = 1 + (normals[m_j].X*normals[m_k].X + - normals[m_j].Y*normals[m_k].Y); - if (m_R >= m_RMin) DoMiter(); else DoSquare(MiterLimit); - break; - } - case jtSquare: DoSquare(); break; - case jtRound: DoRound(); break; - } - m_k = m_j; - } - } - - //finally, clean up untidy corners using Clipper ... - Clipper clpr; - clpr.AddPolygons(out_polys, ptSubject); - if (delta > 0) - { - if (!clpr.Execute(ctUnion, out_polys, pftPositive, pftPositive)) - out_polys.clear(); - } - else - { - IntRect r = clpr.GetBounds(); - Polygon outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPolygon(outer, ptSubject); - if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative)) - { - out_polys.erase(out_polys.begin()); - ReversePolygons(out_polys); - - } else - out_polys.clear(); - } -} -//------------------------------------------------------------------------------ - -private: - -void AddPoint(const IntPoint& pt) -{ - Polygon::size_type len = m_curr_poly->size(); - if (len == m_curr_poly->capacity()) - m_curr_poly->reserve(len + buffLength); - m_curr_poly->push_back(pt); -} -//------------------------------------------------------------------------------ - -void DoSquare(double mul = 1.0) -{ - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) - { - double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); - double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X); - a1 = std::fabs(a2 - a1); - if (a1 > pi) a1 = pi * 2 - a1; - double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul); - pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx), - (long64)(pt1.Y + normals[m_k].X * dx)); - AddPoint(pt1); - pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx), - (long64)(pt2.Y -normals[m_j].X * dx)); - AddPoint(pt2); - } - else - { - AddPoint(pt1); - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); - } -} -//------------------------------------------------------------------------------ - -void DoMiter() -{ - if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) - { - double q = m_delta / m_R; - AddPoint(IntPoint((long64)Round(m_p[m_i][m_j].X + - (normals[m_k].X + normals[m_j].X) * q), - (long64)Round(m_p[m_i][m_j].Y + (normals[m_k].Y + normals[m_j].Y) * q))); - } - else - { - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * - m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * - m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - AddPoint(pt1); - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); - } -} -//------------------------------------------------------------------------------ - -void DoRound() -{ - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - AddPoint(pt1); - //round off reflex angles (ie > 180 deg) unless almost flat (ie < ~10deg). - if ((normals[m_k].X*normals[m_j].Y - normals[m_j].X*normals[m_k].Y) * m_delta >= 0) - { - if (normals[m_j].X * normals[m_k].X + normals[m_j].Y * normals[m_k].Y < 0.985) - { - double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); - double a2 = std::atan2(normals[m_j].Y, normals[m_j].X); - if (m_delta > 0 && a2 < a1) a2 += pi *2; - else if (m_delta < 0 && a2 > a1) a2 -= pi *2; - Polygon arc = BuildArc(m_p[m_i][m_j], a1, a2, m_delta); - for (Polygon::size_type m = 0; m < arc.size(); m++) - AddPoint(arc[m]); - } - } - else - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); -} -//-------------------------------------------------------------------------- - -}; //end PolyOffsetBuilder - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, - double delta, JoinType jointype, double MiterLimit) -{ - if (&out_polys == &in_polys) - { - Polygons poly2(in_polys); - PolyOffsetBuilder(poly2, out_polys, delta, jointype, MiterLimit); - } - else PolyOffsetBuilder(in_polys, out_polys, delta, jointype, MiterLimit); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType) -{ - Clipper c; - c.AddPolygon(in_poly, ptSubject); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType) -{ - Clipper c; - c.AddPolygons(in_polys, ptSubject); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(Polygons &polys, PolyFillType fillType) -{ - SimplifyPolygons(polys, polys, fillType); -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, IntPoint& p) -{ - s << p.X << ' ' << p.Y << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, Polygon &p) -{ - for (Polygon::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, Polygons &p) -{ - for (Polygons::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -} //ClipperLib namespace +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 4.8.8 * +* Date : 30 August 2012 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2012 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24–28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +/******************************************************************************* +* * +* This is a translation of the Delphi Clipper library and the naming style * +* used has retained a Delphi flavour. * +* * +*******************************************************************************/ + +#include "clipper.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace ClipperLib { + +static long64 const loRange = 0x3FFFFFFF; +static long64 const hiRange = 0x3FFFFFFFFFFFFFFFLL; +static double const pi = 3.141592653589793238; +enum Direction { dRightToLeft, dLeftToRight }; + +#define HORIZONTAL (-1.0E+40) +#define TOLERANCE (1.0e-20) +#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) +#define NEAR_EQUAL(a, b) NEAR_ZERO((a) - (b)) + +inline long64 Abs(long64 val) +{ + return val < 0 ? -val : val; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Int128 class (enables safe math on signed 64bit integers) +// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 +// Int128 val2((long64)9223372036854775807); +// Int128 val3 = val1 * val2; +// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) +//------------------------------------------------------------------------------ + +class Int128 +{ + public: + + Int128(long64 _lo = 0) + { + lo = _lo; + if (lo < 0) hi = -1; else hi = 0; + } + + Int128(const Int128 &val): hi(val.hi), lo(val.lo){} + + long64 operator = (const long64 &val) + { + lo = val; + if (lo < 0) hi = -1; else hi = 0; + return val; + } + + bool operator == (const Int128 &val) const + {return (hi == val.hi && lo == val.lo);} + + bool operator != (const Int128 &val) const + { return !(*this == val);} + + bool operator > (const Int128 &val) const + { + if (hi != val.hi) + return hi > val.hi; + else + return lo > val.lo; + } + + bool operator < (const Int128 &val) const + { + if (hi != val.hi) + return hi < val.hi; + else + return lo < val.lo; + } + + bool operator >= (const Int128 &val) const + { return !(*this < val);} + + bool operator <= (const Int128 &val) const + { return !(*this > val);} + + Int128& operator += (const Int128 &rhs) + { + hi += rhs.hi; + lo += rhs.lo; + if (ulong64(lo) < ulong64(rhs.lo)) hi++; + return *this; + } + + Int128 operator + (const Int128 &rhs) const + { + Int128 result(*this); + result+= rhs; + return result; + } + + Int128& operator -= (const Int128 &rhs) + { + Int128 tmp(rhs); + Negate(tmp); + *this += tmp; + return *this; + } + + //Int128 operator -() const + //{ + // Int128 result(*this); + // if (result.lo == 0) { + // if (result.hi != 0) result.hi = -1; + // } + // else { + // result.lo = -result.lo; + // result.hi = ~result.hi; + // } + // return result; + //} + + Int128 operator - (const Int128 &rhs) const + { + Int128 result(*this); + result -= rhs; + return result; + } + + Int128 operator * (const Int128 &rhs) const + { + if ( !(hi == 0 || hi == -1) || !(rhs.hi == 0 || rhs.hi == -1)) + throw "Int128 operator*: overflow error"; + bool negate = (hi < 0) != (rhs.hi < 0); + + Int128 tmp(*this); + if (tmp.hi < 0) Negate(tmp); + ulong64 int1Hi = ulong64(tmp.lo) >> 32; + ulong64 int1Lo = ulong64(tmp.lo & 0xFFFFFFFF); + + tmp = rhs; + if (tmp.hi < 0) Negate(tmp); + ulong64 int2Hi = ulong64(tmp.lo) >> 32; + ulong64 int2Lo = ulong64(tmp.lo & 0xFFFFFFFF); + + //nb: see comments in clipper.pas + ulong64 a = int1Hi * int2Hi; + ulong64 b = int1Lo * int2Lo; + ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; + + tmp.hi = long64(a + (c >> 32)); + tmp.lo = long64(c << 32); + tmp.lo += long64(b); + if (ulong64(tmp.lo) < b) tmp.hi++; + if (negate) Negate(tmp); + return tmp; + } + + Int128 operator/ (const Int128 &rhs) const + { + if (rhs.lo == 0 && rhs.hi == 0) + throw "Int128 operator/: divide by zero"; + bool negate = (rhs.hi < 0) != (hi < 0); + Int128 result(*this), denom(rhs); + if (result.hi < 0) Negate(result); + if (denom.hi < 0) Negate(denom); + if (denom > result) return Int128(0); //result is only a fraction of 1 + Negate(denom); + + Int128 p(0); + for (int i = 0; i < 128; ++i) + { + p.hi = p.hi << 1; + if (p.lo < 0) p.hi++; + p.lo = long64(p.lo) << 1; + if (result.hi < 0) p.lo++; + result.hi = result.hi << 1; + if (result.lo < 0) result.hi++; + result.lo = long64(result.lo) << 1; + Int128 p2(p); + p += denom; + if (p.hi < 0) p = p2; + else result.lo++; + } + if (negate) Negate(result); + return result; + } + + double AsDouble() const + { + const double shift64 = 18446744073709551616.0; //2^64 + const double bit64 = 9223372036854775808.0; + if (hi < 0) + { + Int128 tmp(*this); + Negate(tmp); + if (tmp.lo < 0) + return (double)tmp.lo - bit64 - tmp.hi * shift64; + else + return -(double)tmp.lo - tmp.hi * shift64; + } + else if (lo < 0) + return -(double)lo + bit64 + hi * shift64; + else + return (double)lo + (double)hi * shift64; + } + + //for bug testing ... + //std::string AsString() const + //{ + // std::string result; + // unsigned char r = 0; + // Int128 tmp(0), val(*this); + // if (hi < 0) Negate(val); + // result.resize(50); + // std::string::size_type i = result.size() -1; + // while (val.hi != 0 || val.lo != 0) + // { + // Div10(val, tmp, r); + // result[i--] = char('0' + r); + // val = tmp; + // } + // if (hi < 0) result[i--] = '-'; + // result.erase(0,i+1); + // if (result.size() == 0) result = "0"; + // return result; + //} + +private: + long64 hi; + long64 lo; + + static void Negate(Int128 &val) + { + if (val.lo == 0) { + if (val.hi != 0) val.hi = -val.hi;; + } + else { + val.lo = -val.lo; + val.hi = ~val.hi; + } + } + + //debugging only ... + //void Div10(const Int128 val, Int128& result, unsigned char & remainder) const + //{ + // remainder = 0; + // result = 0; + // for (int i = 63; i >= 0; --i) + // { + // if ((val.hi & ((long64)1 << i)) != 0) + // remainder = char((remainder * 2) + 1); else + // remainder *= char(2); + // if (remainder >= 10) + // { + // result.hi += ((long64)1 << i); + // remainder -= char(10); + // } + // } + // for (int i = 63; i >= 0; --i) + // { + // if ((val.lo & ((long64)1 << i)) != 0) + // remainder = char((remainder * 2) + 1); else + // remainder *= char(2); + // if (remainder >= 10) + // { + // result.lo += ((long64)1 << i); + // remainder -= char(10); + // } + // } + //} +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +bool FullRangeNeeded(const Polygon &pts) +{ + bool result = false; + for (Polygon::size_type i = 0; i < pts.size(); ++i) + { + if (Abs(pts[i].X) > hiRange || Abs(pts[i].Y) > hiRange) + throw "Coordinate exceeds range bounds."; + else if (Abs(pts[i].X) > loRange || Abs(pts[i].Y) > loRange) + result = true; + } + return result; +} +//------------------------------------------------------------------------------ + +bool Orientation(const Polygon &poly) +{ + int highI = (int)poly.size() -1; + if (highI < 2) return false; + + int j = 0, jplus, jminus; + for (int i = 0; i <= highI; ++i) + { + if (poly[i].Y < poly[j].Y) continue; + if ((poly[i].Y > poly[j].Y || poly[i].X < poly[j].X)) j = i; + }; + if (j == highI) jplus = 0; + else jplus = j +1; + if (j == 0) jminus = highI; + else jminus = j -1; + + IntPoint vec1, vec2; + //get cross product of vectors of the edges adjacent to highest point ... + vec1.X = poly[j].X - poly[jminus].X; + vec1.Y = poly[j].Y - poly[jminus].Y; + vec2.X = poly[jplus].X - poly[j].X; + vec2.Y = poly[jplus].Y - poly[j].Y; + + if (Abs(vec1.X) > loRange || Abs(vec1.Y) > loRange || + Abs(vec2.X) > loRange || Abs(vec2.Y) > loRange) + { + if (Abs(vec1.X) > hiRange || Abs(vec1.Y) > hiRange || + Abs(vec2.X) > hiRange || Abs(vec2.Y) > hiRange) + throw "Coordinate exceeds range bounds."; + Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - + Int128(vec2.X) * Int128(vec1.Y); + return cross >= 0; + } + else + return (vec1.X * vec2.Y - vec2.X * vec1.Y) >= 0; +} +//------------------------------------------------------------------------------ + +inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) +{ + return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); +} +//------------------------------------------------------------------------------ + +bool Orientation(OutRec *outRec, bool UseFullInt64Range) +{ + //first make sure bottomPt is correctly assigned ... + OutPt *opBottom = outRec->pts, *op = outRec->pts->next; + while (op != outRec->pts) + { + if (op->pt.Y >= opBottom->pt.Y) + { + if (op->pt.Y > opBottom->pt.Y || op->pt.X < opBottom->pt.X) + opBottom = op; + } + op = op->next; + } + outRec->bottomPt = opBottom; + opBottom->idx = outRec->idx; + + op = opBottom; + //find vertices either side of bottomPt (skipping duplicate points) .... + OutPt *opPrev = op->prev; + OutPt *opNext = op->next; + while (op != opPrev && PointsEqual(op->pt, opPrev->pt)) + opPrev = opPrev->prev; + while (op != opNext && PointsEqual(op->pt, opNext->pt)) + opNext = opNext->next; + + IntPoint ip1, ip2; + ip1.X = op->pt.X - opPrev->pt.X; + ip1.Y = op->pt.Y - opPrev->pt.Y; + ip2.X = opNext->pt.X - op->pt.X; + ip2.Y = opNext->pt.Y - op->pt.Y; + + if (UseFullInt64Range) + return Int128(ip1.X) * Int128(ip2.Y) - Int128(ip2.X) * Int128(ip1.Y) >= 0; + else + return (ip1.X * ip2.Y - ip2.X * ip1.Y) >= 0; +} +//------------------------------------------------------------------------------ + +double Area(const Polygon &poly) +{ + int highI = (int)poly.size() -1; + if (highI < 2) return 0; + + if (FullRangeNeeded(poly)) { + Int128 a; + a = (Int128(poly[highI].X) * Int128(poly[0].Y)) - + Int128(poly[0].X) * Int128(poly[highI].Y); + for (int i = 0; i < highI; ++i) + a += Int128(poly[i].X) * Int128(poly[i+1].Y) - + Int128(poly[i+1].X) * Int128(poly[i].Y); + return a.AsDouble() / 2; + } + else + { + double a; + a = (double)poly[highI].X * poly[0].Y - (double)poly[0].X * poly[highI].Y; + for (int i = 0; i < highI; ++i) + a += (double)poly[i].X * poly[i+1].Y - (double)poly[i+1].X * poly[i].Y; + return a/2; + } +} +//------------------------------------------------------------------------------ + +double Area(const OutRec &outRec, bool UseFullInt64Range) +{ + OutPt *op = outRec.pts; + if (UseFullInt64Range) { + Int128 a(0); + do { + a += (Int128(op->prev->pt.X) * Int128(op->pt.Y)) - + Int128(op->pt.X) * Int128(op->prev->pt.Y); + op = op->next; + } while (op != outRec.pts); + return a.AsDouble() / 2; + } + else + { + double a = 0; + do { + a += (op->prev->pt.X * op->pt.Y) - (op->pt.X * op->prev->pt.Y); + op = op->next; + } while (op != outRec.pts); + return a/2; + } +} +//------------------------------------------------------------------------------ + +bool PointIsVertex(const IntPoint &pt, OutPt *pp) +{ + OutPt *pp2 = pp; + do + { + if (PointsEqual(pp2->pt, pt)) return true; + pp2 = pp2->next; + } + while (pp2 != pp); + return false; +} +//------------------------------------------------------------------------------ + +bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range) +{ + OutPt *pp2 = pp; + bool result = false; + if (UseFullInt64Range) { + do + { + if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || + ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && + Int128(pt.X - pp2->pt.X) < (Int128(pp2->prev->pt.X - pp2->pt.X) * + Int128(pt.Y - pp2->pt.Y)) / Int128(pp2->prev->pt.Y - pp2->pt.Y)) + result = !result; + pp2 = pp2->next; + } + while (pp2 != pp); + } + else + { + do + { + if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || + ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && + (pt.X < (pp2->prev->pt.X - pp2->pt.X) * (pt.Y - pp2->pt.Y) / + (pp2->prev->pt.Y - pp2->pt.Y) + pp2->pt.X )) result = !result; + pp2 = pp2->next; + } + while (pp2 != pp); + } + return result; +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(TEdge &e1, TEdge &e2, bool UseFullInt64Range) +{ + if (UseFullInt64Range) + return Int128(e1.ytop - e1.ybot) * Int128(e2.xtop - e2.xbot) == + Int128(e1.xtop - e1.xbot) * Int128(e2.ytop - e2.ybot); + else return (e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) == + (e1.xtop - e1.xbot)*(e2.ytop - e2.ybot); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, bool UseFullInt64Range) +{ + if (UseFullInt64Range) + return Int128(pt1.Y-pt2.Y) * Int128(pt2.X-pt3.X) == + Int128(pt1.X-pt2.X) * Int128(pt2.Y-pt3.Y); + else return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) +{ + if (UseFullInt64Range) + return Int128(pt1.Y-pt2.Y) * Int128(pt3.X-pt4.X) == + Int128(pt1.X-pt2.X) * Int128(pt3.Y-pt4.Y); + else return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); +} +//------------------------------------------------------------------------------ + +double GetDx(const IntPoint pt1, const IntPoint pt2) +{ + return (pt1.Y == pt2.Y) ? + HORIZONTAL : (double)(pt2.X - pt1.X) / (double)(pt2.Y - pt1.Y); +} +//--------------------------------------------------------------------------- + +void SetDx(TEdge &e) +{ + if (e.ybot == e.ytop) e.dx = HORIZONTAL; + else e.dx = (double)(e.xtop - e.xbot) / (double)(e.ytop - e.ybot); +} +//--------------------------------------------------------------------------- + +void SwapSides(TEdge &edge1, TEdge &edge2) +{ + EdgeSide side = edge1.side; + edge1.side = edge2.side; + edge2.side = side; +} +//------------------------------------------------------------------------------ + +void SwapPolyIndexes(TEdge &edge1, TEdge &edge2) +{ + int outIdx = edge1.outIdx; + edge1.outIdx = edge2.outIdx; + edge2.outIdx = outIdx; +} +//------------------------------------------------------------------------------ + +inline long64 Round(double val) +{ + return (val < 0) ? + static_cast(val - 0.5) : static_cast(val + 0.5); +} +//------------------------------------------------------------------------------ + +long64 TopX(TEdge &edge, const long64 currentY) +{ + return ( currentY == edge.ytop ) ? + edge.xtop : edge.xbot + Round(edge.dx *(currentY - edge.ybot)); +} +//------------------------------------------------------------------------------ + +long64 TopX(const IntPoint pt1, const IntPoint pt2, const long64 currentY) +{ + //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y + if (currentY >= pt1.Y) return pt1.X; + else if (currentY == pt2.Y) return pt2.X; + else if (pt1.X == pt2.X) return pt1.X; + else + { + double q = (double)(pt1.X-pt2.X)/(double)(pt1.Y-pt2.Y); + return Round(pt1.X + (currentY - pt1.Y) *q); + } +} +//------------------------------------------------------------------------------ + +bool IntersectPoint(TEdge &edge1, TEdge &edge2, + IntPoint &ip, bool UseFullInt64Range) +{ + double b1, b2; + if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false; + else if (NEAR_ZERO(edge1.dx)) + { + ip.X = edge1.xbot; + if (NEAR_EQUAL(edge2.dx, HORIZONTAL)) + { + ip.Y = edge2.ybot; + } else + { + b2 = edge2.ybot - (edge2.xbot/edge2.dx); + ip.Y = Round(ip.X/edge2.dx + b2); + } + } + else if (NEAR_ZERO(edge2.dx)) + { + ip.X = edge2.xbot; + if (NEAR_EQUAL(edge1.dx, HORIZONTAL)) + { + ip.Y = edge1.ybot; + } else + { + b1 = edge1.ybot - (edge1.xbot/edge1.dx); + ip.Y = Round(ip.X/edge1.dx + b1); + } + } else + { + b1 = edge1.xbot - edge1.ybot * edge1.dx; + b2 = edge2.xbot - edge2.ybot * edge2.dx; + b2 = (b2-b1)/(edge1.dx - edge2.dx); + ip.Y = Round(b2); + ip.X = Round(edge1.dx * b2 + b1); + } + + return + //can be *so close* to the top of one edge that the rounded Y equals one ytop ... + (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) || + (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) || + (ip.Y > edge1.ytop && ip.Y > edge2.ytop); +} +//------------------------------------------------------------------------------ + +void ReversePolyPtLinks(OutPt &pp) +{ + OutPt *pp1, *pp2; + pp1 = &pp; + do { + pp2 = pp1->next; + pp1->next = pp1->prev; + pp1->prev = pp2; + pp1 = pp2; + } while( pp1 != &pp ); +} +//------------------------------------------------------------------------------ + +void DisposeOutPts(OutPt*& pp) +{ + if (pp == 0) return; + pp->prev->next = 0; + while( pp ) + { + OutPt *tmpPp = pp; + pp = pp->next; + delete tmpPp ; + } +} +//------------------------------------------------------------------------------ + +void InitEdge(TEdge *e, TEdge *eNext, + TEdge *ePrev, const IntPoint &pt, PolyType polyType) +{ + std::memset( e, 0, sizeof( TEdge )); + + e->next = eNext; + e->prev = ePrev; + e->xcurr = pt.X; + e->ycurr = pt.Y; + if (e->ycurr >= e->next->ycurr) + { + e->xbot = e->xcurr; + e->ybot = e->ycurr; + e->xtop = e->next->xcurr; + e->ytop = e->next->ycurr; + e->windDelta = 1; + } else + { + e->xtop = e->xcurr; + e->ytop = e->ycurr; + e->xbot = e->next->xcurr; + e->ybot = e->next->ycurr; + e->windDelta = -1; + } + SetDx(*e); + e->polyType = polyType; + e->outIdx = -1; +} +//------------------------------------------------------------------------------ + +inline void SwapX(TEdge &e) +{ + //swap horizontal edges' top and bottom x's so they follow the natural + //progression of the bounds - ie so their xbots will align with the + //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + e.xcurr = e.xtop; + e.xtop = e.xbot; + e.xbot = e.xcurr; +} +//------------------------------------------------------------------------------ + +void SwapPoints(IntPoint &pt1, IntPoint &pt2) +{ + IntPoint tmp = pt1; + pt1 = pt2; + pt2 = tmp; +} +//------------------------------------------------------------------------------ + +bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, + IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) +{ + //precondition: segments are colinear. + if ( pt1a.Y == pt1b.Y || Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 ) + { + if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); + if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); + if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; + return pt1.X < pt2.X; + } else + { + if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); + if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); + if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; + return pt1.Y > pt2.Y; + } +} +//------------------------------------------------------------------------------ + +bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) +{ + OutPt *p = btmPt1->prev; + while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->prev; + double dx1p = std::fabs(GetDx(btmPt1->pt, p->pt)); + p = btmPt1->next; + while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->next; + double dx1n = std::fabs(GetDx(btmPt1->pt, p->pt)); + + p = btmPt2->prev; + while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->prev; + double dx2p = std::fabs(GetDx(btmPt2->pt, p->pt)); + p = btmPt2->next; + while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->next; + double dx2n = std::fabs(GetDx(btmPt2->pt, p->pt)); + return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); +} +//------------------------------------------------------------------------------ + +OutPt* GetBottomPt(OutPt *pp) +{ + OutPt* dups = 0; + OutPt* p = pp->next; + while (p != pp) + { + if (p->pt.Y > pp->pt.Y) + { + pp = p; + dups = 0; + } + else if (p->pt.Y == pp->pt.Y && p->pt.X <= pp->pt.X) + { + if (p->pt.X < pp->pt.X) + { + dups = 0; + pp = p; + } else + { + if (p->next != pp && p->prev != pp) dups = p; + } + } + p = p->next; + } + if (dups) + { + //there appears to be at least 2 vertices at bottomPt so ... + while (dups != p) + { + if (!FirstIsBottomPt(p, dups)) pp = dups; + dups = dups->next; + while (!PointsEqual(dups->pt, pp->pt)) dups = dups->next; + } + } + return pp; +} +//------------------------------------------------------------------------------ + +bool FindSegment(OutPt* &pp, IntPoint &pt1, IntPoint &pt2) +{ + //outPt1 & outPt2 => the overlap segment (if the function returns true) + if (!pp) return false; + OutPt* pp2 = pp; + IntPoint pt1a = pt1, pt2a = pt2; + do + { + if (SlopesEqual(pt1a, pt2a, pp->pt, pp->prev->pt, true) && + SlopesEqual(pt1a, pt2a, pp->pt, true) && + GetOverlapSegment(pt1a, pt2a, pp->pt, pp->prev->pt, pt1, pt2)) + return true; + pp = pp->next; + } + while (pp != pp2); + return false; +} +//------------------------------------------------------------------------------ + +bool Pt3IsBetweenPt1AndPt2(const IntPoint pt1, + const IntPoint pt2, const IntPoint pt3) +{ + if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; + else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); + else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); +} +//------------------------------------------------------------------------------ + +OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint pt) +{ + if (p1 == p2) throw "JoinError"; + OutPt* result = new OutPt; + result->pt = pt; + if (p2 == p1->next) + { + p1->next = result; + p2->prev = result; + result->next = p2; + result->prev = p1; + } else + { + p2->next = result; + p1->prev = result; + result->next = p1; + result->prev = p2; + } + return result; +} + +//------------------------------------------------------------------------------ +// ClipperBase class methods ... +//------------------------------------------------------------------------------ + +ClipperBase::ClipperBase() //constructor +{ + m_MinimaList = 0; + m_CurrentLM = 0; + m_UseFullRange = true; +} +//------------------------------------------------------------------------------ + +ClipperBase::~ClipperBase() //destructor +{ + Clear(); +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType) +{ + int len = (int)pg.size(); + if (len < 3) return false; + Polygon p(len); + p[0] = pg[0]; + int j = 0; + + long64 maxVal; + if (m_UseFullRange) maxVal = hiRange; else maxVal = loRange; + + for (int i = 0; i < len; ++i) + { + if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) + { + if (Abs(pg[i].X) > hiRange || Abs(pg[i].Y) > hiRange) + throw "Coordinate exceeds range bounds"; + maxVal = hiRange; + m_UseFullRange = true; + } + + if (i == 0 || PointsEqual(p[j], pg[i])) continue; + else if (j > 0 && SlopesEqual(p[j-1], p[j], pg[i], m_UseFullRange)) + { + if (PointsEqual(p[j-1], pg[i])) j--; + } else j++; + p[j] = pg[i]; + } + if (j < 2) return false; + + len = j+1; + while (len > 2) + { + //nb: test for point equality before testing slopes ... + if (PointsEqual(p[j], p[0])) j--; + else if (PointsEqual(p[0], p[1]) || + SlopesEqual(p[j], p[0], p[1], m_UseFullRange)) + p[0] = p[j--]; + else if (SlopesEqual(p[j-1], p[j], p[0], m_UseFullRange)) j--; + else if (SlopesEqual(p[0], p[1], p[2], m_UseFullRange)) + { + for (int i = 2; i <= j; ++i) p[i-1] = p[i]; + j--; + } + else break; + len--; + } + if (len < 3) return false; + + //create a new edge array ... + TEdge *edges = new TEdge [len]; + m_edges.push_back(edges); + + //convert vertices to a double-linked-list of edges and initialize ... + edges[0].xcurr = p[0].X; + edges[0].ycurr = p[0].Y; + InitEdge(&edges[len-1], &edges[0], &edges[len-2], p[len-1], polyType); + for (int i = len-2; i > 0; --i) + InitEdge(&edges[i], &edges[i+1], &edges[i-1], p[i], polyType); + InitEdge(&edges[0], &edges[1], &edges[len-1], p[0], polyType); + + //reset xcurr & ycurr and find 'eHighest' (given the Y axis coordinates + //increase downward so the 'highest' edge will have the smallest ytop) ... + TEdge *e = &edges[0]; + TEdge *eHighest = e; + do + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + if (e->ytop < eHighest->ytop) eHighest = e; + e = e->next; + } + while ( e != &edges[0]); + + //make sure eHighest is positioned so the following loop works safely ... + if (eHighest->windDelta > 0) eHighest = eHighest->next; + if (NEAR_EQUAL(eHighest->dx, HORIZONTAL)) eHighest = eHighest->next; + + //finally insert each local minima ... + e = eHighest; + do { + e = AddBoundsToLML(e); + } + while( e != eHighest ); + return true; +} +//------------------------------------------------------------------------------ + +void ClipperBase::InsertLocalMinima(LocalMinima *newLm) +{ + if( ! m_MinimaList ) + { + m_MinimaList = newLm; + } + else if( newLm->Y >= m_MinimaList->Y ) + { + newLm->next = m_MinimaList; + m_MinimaList = newLm; + } else + { + LocalMinima* tmpLm = m_MinimaList; + while( tmpLm->next && ( newLm->Y < tmpLm->next->Y ) ) + tmpLm = tmpLm->next; + newLm->next = tmpLm->next; + tmpLm->next = newLm; + } +} +//------------------------------------------------------------------------------ + +TEdge* ClipperBase::AddBoundsToLML(TEdge *e) +{ + //Starting at the top of one bound we progress to the bottom where there's + //a local minima. We then go to the top of the next bound. These two bounds + //form the left and right (or right and left) bounds of the local minima. + e->nextInLML = 0; + e = e->next; + for (;;) + { + if (NEAR_EQUAL(e->dx, HORIZONTAL)) + { + //nb: proceed through horizontals when approaching from their right, + // but break on horizontal minima if approaching from their left. + // This ensures 'local minima' are always on the left of horizontals. + if (e->next->ytop < e->ytop && e->next->xbot > e->prev->xbot) break; + if (e->xtop != e->prev->xbot) SwapX(*e); + e->nextInLML = e->prev; + } + else if (e->ycurr == e->prev->ycurr) break; + else e->nextInLML = e->prev; + e = e->next; + } + + //e and e.prev are now at a local minima ... + LocalMinima* newLm = new LocalMinima; + newLm->next = 0; + newLm->Y = e->prev->ybot; + + if ( NEAR_EQUAL(e->dx, HORIZONTAL) ) //horizontal edges never start a left bound + { + if (e->xbot != e->prev->xbot) SwapX(*e); + newLm->leftBound = e->prev; + newLm->rightBound = e; + } else if (e->dx < e->prev->dx) + { + newLm->leftBound = e->prev; + newLm->rightBound = e; + } else + { + newLm->leftBound = e; + newLm->rightBound = e->prev; + } + newLm->leftBound->side = esLeft; + newLm->rightBound->side = esRight; + InsertLocalMinima( newLm ); + + for (;;) + { + if ( e->next->ytop == e->ytop && !NEAR_EQUAL(e->next->dx, HORIZONTAL) ) break; + e->nextInLML = e->next; + e = e->next; + if ( NEAR_EQUAL(e->dx, HORIZONTAL) && e->xbot != e->prev->xtop) SwapX(*e); + } + return e->next; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPolygons(const Polygons &ppg, PolyType polyType) +{ + bool result = false; + for (Polygons::size_type i = 0; i < ppg.size(); ++i) + if (AddPolygon(ppg[i], polyType)) result = true; + return result; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Clear() +{ + DisposeLocalMinimaList(); + for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) delete [] m_edges[i]; + m_edges.clear(); + m_UseFullRange = false; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Reset() +{ + m_CurrentLM = m_MinimaList; + if( !m_CurrentLM ) return; //ie nothing to process + + //reset all edges ... + LocalMinima* lm = m_MinimaList; + while( lm ) + { + TEdge* e = lm->leftBound; + while( e ) + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + e->side = esLeft; + e->outIdx = -1; + e = e->nextInLML; + } + e = lm->rightBound; + while( e ) + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + e->side = esRight; + e->outIdx = -1; + e = e->nextInLML; + } + lm = lm->next; + } +} +//------------------------------------------------------------------------------ + +void ClipperBase::DisposeLocalMinimaList() +{ + while( m_MinimaList ) + { + LocalMinima* tmpLm = m_MinimaList->next; + delete m_MinimaList; + m_MinimaList = tmpLm; + } + m_CurrentLM = 0; +} +//------------------------------------------------------------------------------ + +void ClipperBase::PopLocalMinima() +{ + if( ! m_CurrentLM ) return; + m_CurrentLM = m_CurrentLM->next; +} +//------------------------------------------------------------------------------ + +IntRect ClipperBase::GetBounds() +{ + IntRect result; + LocalMinima* lm = m_MinimaList; + if (!lm) + { + result.left = result.top = result.right = result.bottom = 0; + return result; + } + result.left = lm->leftBound->xbot; + result.top = lm->leftBound->ybot; + result.right = lm->leftBound->xbot; + result.bottom = lm->leftBound->ybot; + while (lm) + { + if (lm->leftBound->ybot > result.bottom) + result.bottom = lm->leftBound->ybot; + TEdge* e = lm->leftBound; + for (;;) { + TEdge* bottomE = e; + while (e->nextInLML) + { + if (e->xbot < result.left) result.left = e->xbot; + if (e->xbot > result.right) result.right = e->xbot; + e = e->nextInLML; + } + if (e->xbot < result.left) result.left = e->xbot; + if (e->xbot > result.right) result.right = e->xbot; + if (e->xtop < result.left) result.left = e->xtop; + if (e->xtop > result.right) result.right = e->xtop; + if (e->ytop < result.top) result.top = e->ytop; + + if (bottomE == lm->leftBound) e = lm->rightBound; + else break; + } + lm = lm->next; + } + return result; +} + + +//------------------------------------------------------------------------------ +// TClipper methods ... +//------------------------------------------------------------------------------ + +Clipper::Clipper() : ClipperBase() //constructor +{ + m_Scanbeam = 0; + m_ActiveEdges = 0; + m_SortedEdges = 0; + m_IntersectNodes = 0; + m_ExecuteLocked = false; + m_UseFullRange = false; + m_ReverseOutput = false; +} +//------------------------------------------------------------------------------ + +Clipper::~Clipper() //destructor +{ + Clear(); + DisposeScanbeamList(); +} +//------------------------------------------------------------------------------ + +void Clipper::Clear() +{ + if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor + DisposeAllPolyPts(); + ClipperBase::Clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeScanbeamList() +{ + while ( m_Scanbeam ) { + Scanbeam* sb2 = m_Scanbeam->next; + delete m_Scanbeam; + m_Scanbeam = sb2; + } +} +//------------------------------------------------------------------------------ + +void Clipper::Reset() +{ + ClipperBase::Reset(); + m_Scanbeam = 0; + m_ActiveEdges = 0; + m_SortedEdges = 0; + DisposeAllPolyPts(); + LocalMinima* lm = m_MinimaList; + while (lm) + { + InsertScanbeam(lm->Y); + InsertScanbeam(lm->leftBound->ytop); + lm = lm->next; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, Polygons &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + bool succeeded = ExecuteInternal(false); + if (succeeded) BuildResult(solution); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, ExPolygons &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + bool succeeded = ExecuteInternal(true); + if (succeeded) BuildResultEx(solution); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool PolySort(OutRec *or1, OutRec *or2) +{ + if (or1 == or2) return false; + if (!or1->pts || !or2->pts) + { + if (or1->pts != or2->pts) + { + return or1->pts ? true : false; + } + else return false; + } + int i1, i2; + if (or1->isHole) + i1 = or1->FirstLeft->idx; else + i1 = or1->idx; + if (or2->isHole) + i2 = or2->FirstLeft->idx; else + i2 = or2->idx; + int result = i1 - i2; + if (result == 0 && (or1->isHole != or2->isHole)) + { + return or1->isHole ? false : true; + } + else return result < 0; +} +//------------------------------------------------------------------------------ + +OutRec* FindAppendLinkEnd(OutRec *outRec) +{ + while (outRec->AppendLink) outRec = outRec->AppendLink; + return outRec; +} +//------------------------------------------------------------------------------ + +void Clipper::FixHoleLinkage(OutRec *outRec) +{ + OutRec *tmp; + if (outRec->bottomPt) + tmp = m_PolyOuts[outRec->bottomPt->idx]->FirstLeft; + else + tmp = outRec->FirstLeft; + if (outRec == tmp) throw clipperException("HoleLinkage error"); + + if (tmp) + { + if (tmp->AppendLink) tmp = FindAppendLinkEnd(tmp); + if (tmp == outRec) tmp = 0; + else if (tmp->isHole) + { + FixHoleLinkage(tmp); + tmp = tmp->FirstLeft; + } + } + outRec->FirstLeft = tmp; + if (!tmp) outRec->isHole = false; + outRec->AppendLink = 0; +} +//------------------------------------------------------------------------------ + +bool Clipper::ExecuteInternal(bool fixHoleLinkages) +{ + bool succeeded; + try { + Reset(); + if (!m_CurrentLM ) return true; + long64 botY = PopScanbeam(); + do { + InsertLocalMinimaIntoAEL(botY); + ClearHorzJoins(); + ProcessHorizontals(); + long64 topY = PopScanbeam(); + succeeded = ProcessIntersections(botY, topY); + if (!succeeded) break; + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + } while( m_Scanbeam ); + } + catch(...) { + succeeded = false; + } + + if (succeeded) + { + //tidy up output polygons and fix orientations where necessary ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *outRec = m_PolyOuts[i]; + if (!outRec->pts) continue; + FixupOutPolygon(*outRec); + if (!outRec->pts) continue; + if (outRec->isHole && fixHoleLinkages) FixHoleLinkage(outRec); + + if (outRec->bottomPt == outRec->bottomFlag && + (Orientation(outRec, m_UseFullRange) != (Area(*outRec, m_UseFullRange) > 0))) + DisposeBottomPt(*outRec); + + if (outRec->isHole == + (m_ReverseOutput ^ Orientation(outRec, m_UseFullRange))) + ReversePolyPtLinks(*outRec->pts); + } + + JoinCommonEdges(fixHoleLinkages); + if (fixHoleLinkages) + std::sort(m_PolyOuts.begin(), m_PolyOuts.end(), PolySort); + } + + ClearJoins(); + ClearHorzJoins(); + return succeeded; +} +//------------------------------------------------------------------------------ + +void Clipper::InsertScanbeam(const long64 Y) +{ + if( !m_Scanbeam ) + { + m_Scanbeam = new Scanbeam; + m_Scanbeam->next = 0; + m_Scanbeam->Y = Y; + } + else if( Y > m_Scanbeam->Y ) + { + Scanbeam* newSb = new Scanbeam; + newSb->Y = Y; + newSb->next = m_Scanbeam; + m_Scanbeam = newSb; + } else + { + Scanbeam* sb2 = m_Scanbeam; + while( sb2->next && ( Y <= sb2->next->Y ) ) sb2 = sb2->next; + if( Y == sb2->Y ) return; //ie ignores duplicates + Scanbeam* newSb = new Scanbeam; + newSb->Y = Y; + newSb->next = sb2->next; + sb2->next = newSb; + } +} +//------------------------------------------------------------------------------ + +long64 Clipper::PopScanbeam() +{ + long64 Y = m_Scanbeam->Y; + Scanbeam* sb2 = m_Scanbeam; + m_Scanbeam = m_Scanbeam->next; + delete sb2; + return Y; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeAllPolyPts(){ + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + DisposeOutRec(i); + m_PolyOuts.clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeOutRec(PolyOutList::size_type index) +{ + OutRec *outRec = m_PolyOuts[index]; + if (outRec->pts) DisposeOutPts(outRec->pts); + delete outRec; + m_PolyOuts[index] = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::SetWindingCount(TEdge &edge) +{ + TEdge *e = edge.prevInAEL; + //find the edge of the same polytype that immediately preceeds 'edge' in AEL + while ( e && e->polyType != edge.polyType ) e = e->prevInAEL; + if ( !e ) + { + edge.windCnt = edge.windDelta; + edge.windCnt2 = 0; + e = m_ActiveEdges; //ie get ready to calc windCnt2 + } else if ( IsEvenOddFillType(edge) ) + { + //EvenOdd filling ... + edge.windCnt = 1; + edge.windCnt2 = e->windCnt2; + e = e->nextInAEL; //ie get ready to calc windCnt2 + } else + { + //nonZero, Positive or Negative filling ... + if ( e->windCnt * e->windDelta < 0 ) + { + if (Abs(e->windCnt) > 1) + { + if (e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; + else edge.windCnt = e->windCnt + edge.windDelta; + } else + edge.windCnt = e->windCnt + e->windDelta + edge.windDelta; + } else + { + if ( Abs(e->windCnt) > 1 && e->windDelta * edge.windDelta < 0) + edge.windCnt = e->windCnt; + else if ( e->windCnt + edge.windDelta == 0 ) + edge.windCnt = e->windCnt; + else edge.windCnt = e->windCnt + edge.windDelta; + } + edge.windCnt2 = e->windCnt2; + e = e->nextInAEL; //ie get ready to calc windCnt2 + } + + //update windCnt2 ... + if ( IsEvenOddAltFillType(edge) ) + { + //EvenOdd filling ... + while ( e != &edge ) + { + edge.windCnt2 = (edge.windCnt2 == 0) ? 1 : 0; + e = e->nextInAEL; + } + } else + { + //nonZero, Positive or Negative filling ... + while ( e != &edge ) + { + edge.windCnt2 += e->windDelta; + e = e->nextInAEL; + } + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddFillType(const TEdge& edge) const +{ + if (edge.polyType == ptSubject) + return m_SubjFillType == pftEvenOdd; else + return m_ClipFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const +{ + if (edge.polyType == ptSubject) + return m_ClipFillType == pftEvenOdd; else + return m_SubjFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsContributing(const TEdge& edge) const +{ + PolyFillType pft, pft2; + if (edge.polyType == ptSubject) + { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } else + { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } + + switch(pft) + { + case pftEvenOdd: + case pftNonZero: + if (Abs(edge.windCnt) != 1) return false; + break; + case pftPositive: + if (edge.windCnt != 1) return false; + break; + default: //pftNegative + if (edge.windCnt != -1) return false; + } + + switch(m_ClipType) + { + case ctIntersection: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 != 0); + case pftPositive: + return (edge.windCnt2 > 0); + default: + return (edge.windCnt2 < 0); + } + case ctUnion: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 == 0); + case pftPositive: + return (edge.windCnt2 <= 0); + default: + return (edge.windCnt2 >= 0); + } + case ctDifference: + if (edge.polyType == ptSubject) + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 == 0); + case pftPositive: + return (edge.windCnt2 <= 0); + default: + return (edge.windCnt2 >= 0); + } + else + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 != 0); + case pftPositive: + return (edge.windCnt2 > 0); + default: + return (edge.windCnt2 < 0); + } + default: + return true; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + TEdge *e, *prevE; + if( NEAR_EQUAL(e2->dx, HORIZONTAL) || ( e1->dx > e2->dx ) ) + { + AddOutPt( e1, pt ); + e2->outIdx = e1->outIdx; + e1->side = esLeft; + e2->side = esRight; + e = e1; + if (e->prevInAEL == e2) + prevE = e2->prevInAEL; + else + prevE = e->prevInAEL; + } else + { + AddOutPt( e2, pt ); + e1->outIdx = e2->outIdx; + e1->side = esRight; + e2->side = esLeft; + e = e2; + if (e->prevInAEL == e1) + prevE = e1->prevInAEL; + else + prevE = e->prevInAEL; + } + if (prevE && prevE->outIdx >= 0 && + (TopX(*prevE, pt.Y) == TopX(*e, pt.Y)) && + SlopesEqual(*e, *prevE, m_UseFullRange)) + AddJoin(e, prevE, -1, -1); +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + AddOutPt( e1, pt ); + if( e1->outIdx == e2->outIdx ) + { + e1->outIdx = -1; + e2->outIdx = -1; + } + else if (e1->outIdx < e2->outIdx) + AppendPolygon(e1, e2); + else + AppendPolygon(e2, e1); +} +//------------------------------------------------------------------------------ + +void Clipper::AddEdgeToSEL(TEdge *edge) +{ + //SEL pointers in PEdge are reused to build a list of horizontal edges. + //However, we don't need to worry about order with horizontal edge processing. + if( !m_SortedEdges ) + { + m_SortedEdges = edge; + edge->prevInSEL = 0; + edge->nextInSEL = 0; + } + else + { + edge->nextInSEL = m_SortedEdges; + edge->prevInSEL = 0; + m_SortedEdges->prevInSEL = edge; + m_SortedEdges = edge; + } +} +//------------------------------------------------------------------------------ + +void Clipper::CopyAELToSEL() +{ + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + if (!m_ActiveEdges) return; + m_SortedEdges->prevInSEL = 0; + e = e->nextInAEL; + while ( e ) + { + e->prevInSEL = e->prevInAEL; + e->prevInSEL->nextInSEL = e; + e->nextInSEL = 0; + e = e->nextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx, int e2OutIdx) +{ + JoinRec* jr = new JoinRec; + if (e1OutIdx >= 0) + jr->poly1Idx = e1OutIdx; else + jr->poly1Idx = e1->outIdx; + jr->pt1a = IntPoint(e1->xcurr, e1->ycurr); + jr->pt1b = IntPoint(e1->xtop, e1->ytop); + if (e2OutIdx >= 0) + jr->poly2Idx = e2OutIdx; else + jr->poly2Idx = e2->outIdx; + jr->pt2a = IntPoint(e2->xcurr, e2->ycurr); + jr->pt2b = IntPoint(e2->xtop, e2->ytop); + m_Joins.push_back(jr); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearJoins() +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + delete m_Joins[i]; + m_Joins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::AddHorzJoin(TEdge *e, int idx) +{ + HorzJoinRec* hj = new HorzJoinRec; + hj->edge = e; + hj->savedIdx = idx; + m_HorizJoins.push_back(hj); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearHorzJoins() +{ + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); i++) + delete m_HorizJoins[i]; + m_HorizJoins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertLocalMinimaIntoAEL( const long64 botY) +{ + while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) + { + TEdge* lb = m_CurrentLM->leftBound; + TEdge* rb = m_CurrentLM->rightBound; + + InsertEdgeIntoAEL( lb ); + InsertScanbeam( lb->ytop ); + InsertEdgeIntoAEL( rb ); + + if (IsEvenOddFillType(*lb)) + { + lb->windDelta = 1; + rb->windDelta = 1; + } + else + { + rb->windDelta = -lb->windDelta; + } + SetWindingCount( *lb ); + rb->windCnt = lb->windCnt; + rb->windCnt2 = lb->windCnt2; + + if( NEAR_EQUAL(rb->dx, HORIZONTAL) ) + { + //nb: only rightbounds can have a horizontal bottom edge + AddEdgeToSEL( rb ); + InsertScanbeam( rb->nextInLML->ytop ); + } + else + InsertScanbeam( rb->ytop ); + + if( IsContributing(*lb) ) + AddLocalMinPoly( lb, rb, IntPoint(lb->xcurr, m_CurrentLM->Y) ); + + //if any output polygons share an edge, they'll need joining later ... + if (rb->outIdx >= 0) + { + if (NEAR_EQUAL(rb->dx, HORIZONTAL)) + { + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + IntPoint pt, pt2; //returned by GetOverlapSegment() but unused here. + HorzJoinRec* hj = m_HorizJoins[i]; + //if horizontals rb and hj.edge overlap, flag for joining later ... + if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), + IntPoint(hj->edge->xtop, hj->edge->ytop), + IntPoint(rb->xbot, rb->ybot), + IntPoint(rb->xtop, rb->ytop), pt, pt2)) + AddJoin(hj->edge, rb, hj->savedIdx); + } + } + } + + if( lb->nextInAEL != rb ) + { + if (rb->outIdx >= 0 && rb->prevInAEL->outIdx >= 0 && + SlopesEqual(*rb->prevInAEL, *rb, m_UseFullRange)) + AddJoin(rb, rb->prevInAEL); + + TEdge* e = lb->nextInAEL; + IntPoint pt = IntPoint(lb->xcurr, lb->ycurr); + while( e != rb ) + { + if(!e) throw clipperException("InsertLocalMinimaIntoAEL: missing rightbound!"); + //nb: For calculating winding counts etc, IntersectEdges() assumes + //that param1 will be to the right of param2 ABOVE the intersection ... + IntersectEdges( rb , e , pt , ipNone); //order important here + e = e->nextInAEL; + } + } + PopLocalMinima(); + } +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromAEL(TEdge *e) +{ + TEdge* AelPrev = e->prevInAEL; + TEdge* AelNext = e->nextInAEL; + if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted + if( AelPrev ) AelPrev->nextInAEL = AelNext; + else m_ActiveEdges = AelNext; + if( AelNext ) AelNext->prevInAEL = AelPrev; + e->nextInAEL = 0; + e->prevInAEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromSEL(TEdge *e) +{ + TEdge* SelPrev = e->prevInSEL; + TEdge* SelNext = e->nextInSEL; + if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted + if( SelPrev ) SelPrev->nextInSEL = SelNext; + else m_SortedEdges = SelNext; + if( SelNext ) SelNext->prevInSEL = SelPrev; + e->nextInSEL = 0; + e->prevInSEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &pt, IntersectProtects protects) +{ + //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before + //e2 in AEL except when e1 is being inserted at the intersection point ... + bool e1stops = !(ipLeft & protects) && !e1->nextInLML && + e1->xtop == pt.X && e1->ytop == pt.Y; + bool e2stops = !(ipRight & protects) && !e2->nextInLML && + e2->xtop == pt.X && e2->ytop == pt.Y; + bool e1Contributing = ( e1->outIdx >= 0 ); + bool e2contributing = ( e2->outIdx >= 0 ); + + //update winding counts... + //assumes that e1 will be to the right of e2 ABOVE the intersection + if ( e1->polyType == e2->polyType ) + { + if ( IsEvenOddFillType( *e1) ) + { + int oldE1WindCnt = e1->windCnt; + e1->windCnt = e2->windCnt; + e2->windCnt = oldE1WindCnt; + } else + { + if (e1->windCnt + e2->windDelta == 0 ) e1->windCnt = -e1->windCnt; + else e1->windCnt += e2->windDelta; + if ( e2->windCnt - e1->windDelta == 0 ) e2->windCnt = -e2->windCnt; + else e2->windCnt -= e1->windDelta; + } + } else + { + if (!IsEvenOddFillType(*e2)) e1->windCnt2 += e2->windDelta; + else e1->windCnt2 = ( e1->windCnt2 == 0 ) ? 1 : 0; + if (!IsEvenOddFillType(*e1)) e2->windCnt2 -= e1->windDelta; + else e2->windCnt2 = ( e2->windCnt2 == 0 ) ? 1 : 0; + } + + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1->polyType == ptSubject) + { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; + } else + { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2->polyType == ptSubject) + { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } else + { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + long64 e1Wc, e2Wc; + switch (e1FillType) + { + case pftPositive: e1Wc = e1->windCnt; break; + case pftNegative: e1Wc = -e1->windCnt; break; + default: e1Wc = Abs(e1->windCnt); + } + switch(e2FillType) + { + case pftPositive: e2Wc = e2->windCnt; break; + case pftNegative: e2Wc = -e2->windCnt; break; + default: e2Wc = Abs(e2->windCnt); + } + + if ( e1Contributing && e2contributing ) + { + if ( e1stops || e2stops || + (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || + (e1->polyType != e2->polyType && m_ClipType != ctXor) ) + AddLocalMaxPoly(e1, e2, pt); + else + DoBothEdges( e1, e2, pt ); + } + else if ( e1Contributing ) + { + if ((e2Wc == 0 || e2Wc == 1) && + (m_ClipType != ctIntersection || + e2->polyType == ptSubject || (e2->windCnt2 != 0))) + DoEdge1(e1, e2, pt); + } + else if ( e2contributing ) + { + if ((e1Wc == 0 || e1Wc == 1) && + (m_ClipType != ctIntersection || + e1->polyType == ptSubject || (e1->windCnt2 != 0))) + DoEdge2(e1, e2, pt); + } + else if ( (e1Wc == 0 || e1Wc == 1) && + (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) + { + //neither edge is currently contributing ... + + long64 e1Wc2, e2Wc2; + switch (e1FillType2) + { + case pftPositive: e1Wc2 = e1->windCnt2; break; + case pftNegative : e1Wc2 = -e1->windCnt2; break; + default: e1Wc2 = Abs(e1->windCnt2); + } + switch (e2FillType2) + { + case pftPositive: e2Wc2 = e2->windCnt2; break; + case pftNegative: e2Wc2 = -e2->windCnt2; break; + default: e2Wc2 = Abs(e2->windCnt2); + } + + if (e1->polyType != e2->polyType) + AddLocalMinPoly(e1, e2, pt); + else if (e1Wc == 1 && e2Wc == 1) + switch( m_ClipType ) { + case ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) + AddLocalMinPoly(e1, e2, pt); + break; + case ctUnion: + if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) + AddLocalMinPoly(e1, e2, pt); + break; + case ctDifference: + if (((e1->polyType == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || + ((e1->polyType == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) + AddLocalMinPoly(e1, e2, pt); + break; + case ctXor: + AddLocalMinPoly(e1, e2, pt); + } + else + SwapSides( *e1, *e2 ); + } + + if( (e1stops != e2stops) && + ( (e1stops && (e1->outIdx >= 0)) || (e2stops && (e2->outIdx >= 0)) ) ) + { + SwapSides( *e1, *e2 ); + SwapPolyIndexes( *e1, *e2 ); + } + + //finally, delete any non-contributing maxima edges ... + if( e1stops ) DeleteFromAEL( e1 ); + if( e2stops ) DeleteFromAEL( e2 ); +} +//------------------------------------------------------------------------------ + +void Clipper::SetHoleState(TEdge *e, OutRec *outRec) +{ + bool isHole = false; + TEdge *e2 = e->prevInAEL; + while (e2) + { + if (e2->outIdx >= 0) + { + isHole = !isHole; + if (! outRec->FirstLeft) + outRec->FirstLeft = m_PolyOuts[e2->outIdx]; + } + e2 = e2->prevInAEL; + } + if (isHole) outRec->isHole = true; +} +//------------------------------------------------------------------------------ + +OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) +{ + //work out which polygon fragment has the correct hole state ... + OutPt *outPt1 = outRec1->bottomPt; + OutPt *outPt2 = outRec2->bottomPt; + if (outPt1->pt.Y > outPt2->pt.Y) return outRec1; + else if (outPt1->pt.Y < outPt2->pt.Y) return outRec2; + else if (outPt1->pt.X < outPt2->pt.X) return outRec1; + else if (outPt1->pt.X > outPt2->pt.X) return outRec2; + else if (outPt1->next == outPt1) return outRec2; + else if (outPt2->next == outPt2) return outRec1; + else if (FirstIsBottomPt(outPt1, outPt2)) return outRec1; + else return outRec2; +} +//------------------------------------------------------------------------------ + +bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) +{ + do + { + outRec1 = outRec1->FirstLeft; + if (outRec1 == outRec2) return true; + } while (outRec1); + return false; +} +//------------------------------------------------------------------------------ + +void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) +{ + //get the start and ends of both output polygons ... + OutRec *outRec1 = m_PolyOuts[e1->outIdx]; + OutRec *outRec2 = m_PolyOuts[e2->outIdx]; + + OutRec *holeStateRec; + if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; + else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; + else holeStateRec = GetLowermostRec(outRec1, outRec2); + + OutPt* p1_lft = outRec1->pts; + OutPt* p1_rt = p1_lft->prev; + OutPt* p2_lft = outRec2->pts; + OutPt* p2_rt = p2_lft->prev; + + EdgeSide side; + //join e2 poly onto e1 poly and delete pointers to e2 ... + if( e1->side == esLeft ) + { + if( e2->side == esLeft ) + { + //z y x a b c + ReversePolyPtLinks(*p2_lft); + p2_lft->next = p1_lft; + p1_lft->prev = p2_lft; + p1_rt->next = p2_rt; + p2_rt->prev = p1_rt; + outRec1->pts = p2_rt; + } else + { + //x y z a b c + p2_rt->next = p1_lft; + p1_lft->prev = p2_rt; + p2_lft->prev = p1_rt; + p1_rt->next = p2_lft; + outRec1->pts = p2_lft; + } + side = esLeft; + } else + { + if( e2->side == esRight ) + { + //a b c z y x + ReversePolyPtLinks( *p2_lft ); + p1_rt->next = p2_rt; + p2_rt->prev = p1_rt; + p2_lft->next = p1_lft; + p1_lft->prev = p2_lft; + } else + { + //a b c x y z + p1_rt->next = p2_lft; + p2_lft->prev = p1_rt; + p1_lft->prev = p2_rt; + p2_rt->next = p1_lft; + } + side = esRight; + } + + if (holeStateRec == outRec2) + { + outRec1->bottomPt = outRec2->bottomPt; + outRec1->bottomPt->idx = outRec1->idx; + if (outRec2->FirstLeft != outRec1) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec1->isHole = outRec2->isHole; + } + outRec2->pts = 0; + outRec2->bottomPt = 0; + outRec2->AppendLink = outRec1; + int OKIdx = e1->outIdx; + int ObsoleteIdx = e2->outIdx; + + e1->outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly + e2->outIdx = -1; + + TEdge* e = m_ActiveEdges; + while( e ) + { + if( e->outIdx == ObsoleteIdx ) + { + e->outIdx = OKIdx; + e->side = side; + break; + } + e = e->nextInAEL; + } + + for (JoinList::size_type i = 0; i < m_Joins.size(); ++i) + { + if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx; + if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx; + } + + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + if (m_HorizJoins[i]->savedIdx == ObsoleteIdx) + m_HorizJoins[i]->savedIdx = OKIdx; + } + +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::CreateOutRec() +{ + OutRec* result = new OutRec; + result->isHole = false; + result->FirstLeft = 0; + result->AppendLink = 0; + result->pts = 0; + result->bottomPt = 0; + result->sides = esNeither; + result->bottomFlag = 0; + + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeBottomPt(OutRec &outRec) +{ + OutPt* next = outRec.bottomPt->next; + OutPt* prev = outRec.bottomPt->prev; + if (outRec.pts == outRec.bottomPt) outRec.pts = next; + delete outRec.bottomPt; + next->prev = prev; + prev->next = next; + outRec.bottomPt = next; + FixupOutPolygon(outRec); +} +//------------------------------------------------------------------------------ + +void Clipper::AddOutPt(TEdge *e, const IntPoint &pt) +{ + bool ToFront = (e->side == esLeft); + if( e->outIdx < 0 ) + { + OutRec *outRec = CreateOutRec(); + m_PolyOuts.push_back(outRec); + outRec->idx = (int)m_PolyOuts.size()-1; + e->outIdx = outRec->idx; + OutPt* op = new OutPt; + outRec->pts = op; + outRec->bottomPt = op; + op->pt = pt; + op->idx = outRec->idx; + op->next = op; + op->prev = op; + SetHoleState(e, outRec); + } else + { + OutRec *outRec = m_PolyOuts[e->outIdx]; + OutPt* op = outRec->pts; + if ((ToFront && PointsEqual(pt, op->pt)) || + (!ToFront && PointsEqual(pt, op->prev->pt))) return; + + if ((e->side | outRec->sides) != outRec->sides) + { + //check for 'rounding' artefacts ... + if (outRec->sides == esNeither && pt.Y == op->pt.Y) + { + if (ToFront) + { + if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt + } + else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt + } + + outRec->sides = (EdgeSide)(outRec->sides | e->side); + if (outRec->sides == esBoth) + { + //A vertex from each side has now been added. + //Vertices of one side of an output polygon are quite commonly close to + //or even 'touching' edges of the other side of the output polygon. + //Very occasionally vertices from one side can 'cross' an edge on the + //the other side. The distance 'crossed' is always less that a unit + //and is purely an artefact of coordinate rounding. Nevertheless, this + //results in very tiny self-intersections. Because of the way + //orientation is calculated, even tiny self-intersections can cause + //the Orientation function to return the wrong result. Therefore, it's + //important to ensure that any self-intersections close to BottomPt are + //detected and removed before orientation is assigned. + + OutPt *opBot, *op2; + if (ToFront) + { + opBot = outRec->pts; + op2 = opBot->next; //op2 == right side + if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && + ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) < + (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) + outRec->bottomFlag = opBot; + } else + { + opBot = outRec->pts->prev; + op2 = opBot->prev; //op2 == left side + if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && + ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) > + (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) + outRec->bottomFlag = opBot; + } + } + } + + OutPt* op2 = new OutPt; + op2->pt = pt; + op2->idx = outRec->idx; + if (op2->pt.Y == outRec->bottomPt->pt.Y && + op2->pt.X < outRec->bottomPt->pt.X) + outRec->bottomPt = op2; + op2->next = op; + op2->prev = op->prev; + op2->prev->next = op2; + op->prev = op2; + if (ToFront) outRec->pts = op2; + } +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontals() +{ + TEdge* horzEdge = m_SortedEdges; + while( horzEdge ) + { + DeleteFromSEL( horzEdge ); + ProcessHorizontal( horzEdge ); + horzEdge = m_SortedEdges; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsTopHorz(const long64 XPos) +{ + TEdge* e = m_SortedEdges; + while( e ) + { + if( ( XPos >= std::min(e->xcurr, e->xtop) ) && + ( XPos <= std::max(e->xcurr, e->xtop) ) ) return false; + e = e->nextInSEL; + } + return true; +} +//------------------------------------------------------------------------------ + +bool IsMinima(TEdge *e) +{ + return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e); +} +//------------------------------------------------------------------------------ + +bool IsMaxima(TEdge *e, const long64 Y) +{ + return e && e->ytop == Y && !e->nextInLML; +} +//------------------------------------------------------------------------------ + +bool IsIntermediate(TEdge *e, const long64 Y) +{ + return e->ytop == Y && e->nextInLML; +} +//------------------------------------------------------------------------------ + +TEdge *GetMaximaPair(TEdge *e) +{ + if( !IsMaxima(e->next, e->ytop) || e->next->xtop != e->xtop ) + return e->prev; else + return e->next; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInAEL(TEdge *edge1, TEdge *edge2) +{ + if( !edge1->nextInAEL && !edge1->prevInAEL ) return; + if( !edge2->nextInAEL && !edge2->prevInAEL ) return; + + if( edge1->nextInAEL == edge2 ) + { + TEdge* next = edge2->nextInAEL; + if( next ) next->prevInAEL = edge1; + TEdge* prev = edge1->prevInAEL; + if( prev ) prev->nextInAEL = edge2; + edge2->prevInAEL = prev; + edge2->nextInAEL = edge1; + edge1->prevInAEL = edge2; + edge1->nextInAEL = next; + } + else if( edge2->nextInAEL == edge1 ) + { + TEdge* next = edge1->nextInAEL; + if( next ) next->prevInAEL = edge2; + TEdge* prev = edge2->prevInAEL; + if( prev ) prev->nextInAEL = edge1; + edge1->prevInAEL = prev; + edge1->nextInAEL = edge2; + edge2->prevInAEL = edge1; + edge2->nextInAEL = next; + } + else + { + TEdge* next = edge1->nextInAEL; + TEdge* prev = edge1->prevInAEL; + edge1->nextInAEL = edge2->nextInAEL; + if( edge1->nextInAEL ) edge1->nextInAEL->prevInAEL = edge1; + edge1->prevInAEL = edge2->prevInAEL; + if( edge1->prevInAEL ) edge1->prevInAEL->nextInAEL = edge1; + edge2->nextInAEL = next; + if( edge2->nextInAEL ) edge2->nextInAEL->prevInAEL = edge2; + edge2->prevInAEL = prev; + if( edge2->prevInAEL ) edge2->prevInAEL->nextInAEL = edge2; + } + + if( !edge1->prevInAEL ) m_ActiveEdges = edge1; + else if( !edge2->prevInAEL ) m_ActiveEdges = edge2; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) +{ + if( !( edge1->nextInSEL ) && !( edge1->prevInSEL ) ) return; + if( !( edge2->nextInSEL ) && !( edge2->prevInSEL ) ) return; + + if( edge1->nextInSEL == edge2 ) + { + TEdge* next = edge2->nextInSEL; + if( next ) next->prevInSEL = edge1; + TEdge* prev = edge1->prevInSEL; + if( prev ) prev->nextInSEL = edge2; + edge2->prevInSEL = prev; + edge2->nextInSEL = edge1; + edge1->prevInSEL = edge2; + edge1->nextInSEL = next; + } + else if( edge2->nextInSEL == edge1 ) + { + TEdge* next = edge1->nextInSEL; + if( next ) next->prevInSEL = edge2; + TEdge* prev = edge2->prevInSEL; + if( prev ) prev->nextInSEL = edge1; + edge1->prevInSEL = prev; + edge1->nextInSEL = edge2; + edge2->prevInSEL = edge1; + edge2->nextInSEL = next; + } + else + { + TEdge* next = edge1->nextInSEL; + TEdge* prev = edge1->prevInSEL; + edge1->nextInSEL = edge2->nextInSEL; + if( edge1->nextInSEL ) edge1->nextInSEL->prevInSEL = edge1; + edge1->prevInSEL = edge2->prevInSEL; + if( edge1->prevInSEL ) edge1->prevInSEL->nextInSEL = edge1; + edge2->nextInSEL = next; + if( edge2->nextInSEL ) edge2->nextInSEL->prevInSEL = edge2; + edge2->prevInSEL = prev; + if( edge2->prevInSEL ) edge2->prevInSEL->nextInSEL = edge2; + } + + if( !edge1->prevInSEL ) m_SortedEdges = edge1; + else if( !edge2->prevInSEL ) m_SortedEdges = edge2; +} +//------------------------------------------------------------------------------ + +TEdge* GetNextInAEL(TEdge *e, Direction dir) +{ + return dir == dLeftToRight ? e->nextInAEL : e->prevInAEL; +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontal(TEdge *horzEdge) +{ + Direction dir; + long64 horzLeft, horzRight; + + if( horzEdge->xcurr < horzEdge->xtop ) + { + horzLeft = horzEdge->xcurr; + horzRight = horzEdge->xtop; + dir = dLeftToRight; + } else + { + horzLeft = horzEdge->xtop; + horzRight = horzEdge->xcurr; + dir = dRightToLeft; + } + + TEdge* eMaxPair; + if( horzEdge->nextInLML ) eMaxPair = 0; + else eMaxPair = GetMaximaPair(horzEdge); + + TEdge* e = GetNextInAEL( horzEdge , dir ); + while( e ) + { + TEdge* eNext = GetNextInAEL( e, dir ); + + if (eMaxPair || + ((dir == dLeftToRight) && (e->xcurr <= horzRight)) || + ((dir == dRightToLeft) && (e->xcurr >= horzLeft))) + { + //ok, so far it looks like we're still in range of the horizontal edge + if ( e->xcurr == horzEdge->xtop && !eMaxPair ) + { + if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) + { + //if output polygons share an edge, they'll need joining later ... + if (horzEdge->outIdx >= 0 && e->outIdx >= 0) + AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx); + break; //we've reached the end of the horizontal line + } + else if (e->dx < horzEdge->nextInLML->dx) + //we really have got to the end of the intermediate horz edge so quit. + //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal. + break; + } + + if( e == eMaxPair ) + { + //horzEdge is evidently a maxima horizontal and we've arrived at its end. + if (dir == dLeftToRight) + IntersectEdges(horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); + else + IntersectEdges(e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); + if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); + return; + } + else if( NEAR_EQUAL(e->dx, HORIZONTAL) && !IsMinima(e) && !(e->xcurr > e->xtop) ) + { + //An overlapping horizontal edge. Overlapping horizontal edges are + //processed as if layered with the current horizontal edge (horizEdge) + //being infinitesimally lower that the next (e). Therfore, we + //intersect with e only if e.xcurr is within the bounds of horzEdge ... + if( dir == dLeftToRight ) + IntersectEdges( horzEdge , e, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); + else + IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); + } + else if( dir == dLeftToRight ) + { + IntersectEdges( horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); + } + else + { + IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); + } + SwapPositionsInAEL( horzEdge, e ); + } + else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) || + (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break; + e = eNext; + } //end while + + if( horzEdge->nextInLML ) + { + if( horzEdge->outIdx >= 0 ) + AddOutPt( horzEdge, IntPoint(horzEdge->xtop, horzEdge->ytop)); + UpdateEdgeIntoAEL( horzEdge ); + } + else + { + if ( horzEdge->outIdx >= 0 ) + IntersectEdges( horzEdge, eMaxPair, + IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); + if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); + DeleteFromAEL(eMaxPair); + DeleteFromAEL(horzEdge); + } +} +//------------------------------------------------------------------------------ + +void Clipper::UpdateEdgeIntoAEL(TEdge *&e) +{ + if( !e->nextInLML ) throw + clipperException("UpdateEdgeIntoAEL: invalid call"); + TEdge* AelPrev = e->prevInAEL; + TEdge* AelNext = e->nextInAEL; + e->nextInLML->outIdx = e->outIdx; + if( AelPrev ) AelPrev->nextInAEL = e->nextInLML; + else m_ActiveEdges = e->nextInLML; + if( AelNext ) AelNext->prevInAEL = e->nextInLML; + e->nextInLML->side = e->side; + e->nextInLML->windDelta = e->windDelta; + e->nextInLML->windCnt = e->windCnt; + e->nextInLML->windCnt2 = e->windCnt2; + e = e->nextInLML; + e->prevInAEL = AelPrev; + e->nextInAEL = AelNext; + if( !NEAR_EQUAL(e->dx, HORIZONTAL) ) InsertScanbeam( e->ytop ); +} +//------------------------------------------------------------------------------ + +bool Clipper::ProcessIntersections(const long64 botY, const long64 topY) +{ + if( !m_ActiveEdges ) return true; + try { + BuildIntersectList(botY, topY); + if ( !m_IntersectNodes) return true; + if ( FixupIntersections() ) ProcessIntersectList(); + else return false; + } + catch(...) { + m_SortedEdges = 0; + DisposeIntersectNodes(); + throw clipperException("ProcessIntersections error"); + } + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeIntersectNodes() +{ + while ( m_IntersectNodes ) + { + IntersectNode* iNode = m_IntersectNodes->next; + delete m_IntersectNodes; + m_IntersectNodes = iNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildIntersectList(const long64 botY, const long64 topY) +{ + if ( !m_ActiveEdges ) return; + + //prepare for sorting ... + TEdge* e = m_ActiveEdges; + e->tmpX = TopX( *e, topY ); + m_SortedEdges = e; + m_SortedEdges->prevInSEL = 0; + e = e->nextInAEL; + while( e ) + { + e->prevInSEL = e->prevInAEL; + e->prevInSEL->nextInSEL = e; + e->nextInSEL = 0; + e->tmpX = TopX( *e, topY ); + e = e->nextInAEL; + } + + //bubblesort ... + bool isModified = true; + while( isModified && m_SortedEdges ) + { + isModified = false; + e = m_SortedEdges; + while( e->nextInSEL ) + { + TEdge *eNext = e->nextInSEL; + IntPoint pt; + if(e->tmpX > eNext->tmpX && + IntersectPoint(*e, *eNext, pt, m_UseFullRange)) + { + if (pt.Y > botY) + { + pt.Y = botY; + pt.X = TopX(*e, pt.Y); + } + AddIntersectNode( e, eNext, pt ); + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else + e = eNext; + } + if( e->prevInSEL ) e->prevInSEL->nextInSEL = 0; + else break; + } + m_SortedEdges = 0; +} +//------------------------------------------------------------------------------ + +bool ProcessParam1BeforeParam2(IntersectNode &node1, IntersectNode &node2) +{ + bool result; + if (node1.pt.Y == node2.pt.Y) + { + if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) + { + result = node2.pt.X > node1.pt.X; + return node2.edge1->dx > 0 ? !result : result; + } + else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) + { + result = node2.pt.X > node1.pt.X; + return node2.edge2->dx > 0 ? !result : result; + } + else return node2.pt.X > node1.pt.X; + } + else return node1.pt.Y > node2.pt.Y; +} +//------------------------------------------------------------------------------ + +void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + IntersectNode* newNode = new IntersectNode; + newNode->edge1 = e1; + newNode->edge2 = e2; + newNode->pt = pt; + newNode->next = 0; + if( !m_IntersectNodes ) m_IntersectNodes = newNode; + else if( ProcessParam1BeforeParam2(*newNode, *m_IntersectNodes) ) + { + newNode->next = m_IntersectNodes; + m_IntersectNodes = newNode; + } + else + { + IntersectNode* iNode = m_IntersectNodes; + while( iNode->next && ProcessParam1BeforeParam2(*iNode->next, *newNode) ) + iNode = iNode->next; + newNode->next = iNode->next; + iNode->next = newNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessIntersectList() +{ + while( m_IntersectNodes ) + { + IntersectNode* iNode = m_IntersectNodes->next; + { + IntersectEdges( m_IntersectNodes->edge1 , + m_IntersectNodes->edge2 , m_IntersectNodes->pt, ipBoth ); + SwapPositionsInAEL( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 ); + } + delete m_IntersectNodes; + m_IntersectNodes = iNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::DoMaxima(TEdge *e, long64 topY) +{ + TEdge* eMaxPair = GetMaximaPair(e); + long64 X = e->xtop; + TEdge* eNext = e->nextInAEL; + while( eNext != eMaxPair ) + { + if (!eNext) throw clipperException("DoMaxima error"); + IntersectEdges( e, eNext, IntPoint(X, topY), ipBoth ); + eNext = eNext->nextInAEL; + } + if( e->outIdx < 0 && eMaxPair->outIdx < 0 ) + { + DeleteFromAEL( e ); + DeleteFromAEL( eMaxPair ); + } + else if( e->outIdx >= 0 && eMaxPair->outIdx >= 0 ) + { + IntersectEdges( e, eMaxPair, IntPoint(X, topY), ipNone ); + } + else throw clipperException("DoMaxima error"); +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY) +{ + TEdge* e = m_ActiveEdges; + while( e ) + { + //1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + if( IsMaxima(e, topY) && !NEAR_EQUAL(GetMaximaPair(e)->dx, HORIZONTAL) ) + { + //'e' might be removed from AEL, as may any following edges so ... + TEdge* ePrior = e->prevInAEL; + DoMaxima(e, topY); + if( !ePrior ) e = m_ActiveEdges; + else e = ePrior->nextInAEL; + } + else + { + //2. promote horizontal edges, otherwise update xcurr and ycurr ... + if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) ) + { + if (e->outIdx >= 0) + { + AddOutPt(e, IntPoint(e->xtop, e->ytop)); + + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + IntPoint pt, pt2; + HorzJoinRec* hj = m_HorizJoins[i]; + if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), + IntPoint(hj->edge->xtop, hj->edge->ytop), + IntPoint(e->nextInLML->xbot, e->nextInLML->ybot), + IntPoint(e->nextInLML->xtop, e->nextInLML->ytop), pt, pt2)) + AddJoin(hj->edge, e->nextInLML, hj->savedIdx, e->outIdx); + } + + AddHorzJoin(e->nextInLML, e->outIdx); + } + UpdateEdgeIntoAEL(e); + AddEdgeToSEL(e); + } else + { + //this just simplifies horizontal processing ... + e->xcurr = TopX( *e, topY ); + e->ycurr = topY; + } + e = e->nextInAEL; + } + } + + //3. Process horizontals at the top of the scanbeam ... + ProcessHorizontals(); + + //4. Promote intermediate vertices ... + e = m_ActiveEdges; + while( e ) + { + if( IsIntermediate( e, topY ) ) + { + if( e->outIdx >= 0 ) AddOutPt(e, IntPoint(e->xtop,e->ytop)); + UpdateEdgeIntoAEL(e); + + //if output polygons share an edge, they'll need joining later ... + if (e->outIdx >= 0 && e->prevInAEL && e->prevInAEL->outIdx >= 0 && + e->prevInAEL->xcurr == e->xbot && e->prevInAEL->ycurr == e->ybot && + SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), + IntPoint(e->xbot,e->ybot), + IntPoint(e->prevInAEL->xtop, e->prevInAEL->ytop), m_UseFullRange)) + { + AddOutPt(e->prevInAEL, IntPoint(e->xbot, e->ybot)); + AddJoin(e, e->prevInAEL); + } + else if (e->outIdx >= 0 && e->nextInAEL && e->nextInAEL->outIdx >= 0 && + e->nextInAEL->ycurr > e->nextInAEL->ytop && + e->nextInAEL->ycurr <= e->nextInAEL->ybot && + e->nextInAEL->xcurr == e->xbot && e->nextInAEL->ycurr == e->ybot && + SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), + IntPoint(e->xbot,e->ybot), + IntPoint(e->nextInAEL->xtop, e->nextInAEL->ytop), m_UseFullRange)) + { + AddOutPt(e->nextInAEL, IntPoint(e->xbot, e->ybot)); + AddJoin(e, e->nextInAEL); + } + } + e = e->nextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolygon(OutRec &outRec) +{ + //FixupOutPolygon() - removes duplicate points and simplifies consecutive + //parallel edges by removing the middle vertex. + OutPt *lastOK = 0; + outRec.pts = outRec.bottomPt; + OutPt *pp = outRec.bottomPt; + + for (;;) + { + if (pp->prev == pp || pp->prev == pp->next ) + { + DisposeOutPts(pp); + outRec.pts = 0; + outRec.bottomPt = 0; + return; + } + //test for duplicate points and for same slope (cross-product) ... + if ( PointsEqual(pp->pt, pp->next->pt) || + SlopesEqual(pp->prev->pt, pp->pt, pp->next->pt, m_UseFullRange) ) + { + lastOK = 0; + OutPt *tmp = pp; + if (pp == outRec.bottomPt) + outRec.bottomPt = 0; //flags need for updating + pp->prev->next = pp->next; + pp->next->prev = pp->prev; + pp = pp->prev; + delete tmp; + } + else if (pp == lastOK) break; + else + { + if (!lastOK) lastOK = pp; + pp = pp->next; + } + } + if (!outRec.bottomPt) { + outRec.bottomPt = GetBottomPt(pp); + outRec.bottomPt->idx = outRec.idx; + outRec.pts = outRec.bottomPt; + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult(Polygons &polys) +{ + int k = 0; + polys.resize(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + if (m_PolyOuts[i]->pts) + { + Polygon* pg = &polys[k]; + pg->clear(); + OutPt* p = m_PolyOuts[i]->pts; + do + { + pg->push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + //make sure each polygon has at least 3 vertices ... + if (pg->size() < 3) pg->clear(); else k++; + } + } + polys.resize(k); +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResultEx(ExPolygons &polys) +{ + PolyOutList::size_type i = 0; + int k = 0; + polys.resize(0); + polys.reserve(m_PolyOuts.size()); + while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts) + { + ExPolygon epg; + OutPt* p = m_PolyOuts[i]->pts; + do { + epg.outer.push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + i++; + //make sure polygons have at least 3 vertices ... + if (epg.outer.size() < 3) continue; + while (i < m_PolyOuts.size() + && m_PolyOuts[i]->pts && m_PolyOuts[i]->isHole) + { + Polygon pg; + p = m_PolyOuts[i]->pts; + do { + pg.push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + epg.holes.push_back(pg); + i++; + } + polys.push_back(epg); + k++; + } + polys.resize(k); +} +//------------------------------------------------------------------------------ + +void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) +{ + TEdge *e1 = int1.edge1; + TEdge *e2 = int1.edge2; + IntPoint p = int1.pt; + + int1.edge1 = int2.edge1; + int1.edge2 = int2.edge2; + int1.pt = int2.pt; + + int2.edge1 = e1; + int2.edge2 = e2; + int2.pt = p; +} +//------------------------------------------------------------------------------ + +bool Clipper::FixupIntersections() +{ + if ( !m_IntersectNodes->next ) return true; + + CopyAELToSEL(); + IntersectNode *int1 = m_IntersectNodes; + IntersectNode *int2 = m_IntersectNodes->next; + while (int2) + { + TEdge *e1 = int1->edge1; + TEdge *e2; + if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL; + else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL; + else + { + //The current intersection is out of order, so try and swap it with + //a subsequent intersection ... + while (int2) + { + if (int2->edge1->nextInSEL == int2->edge2 || + int2->edge1->prevInSEL == int2->edge2) break; + else int2 = int2->next; + } + if ( !int2 ) return false; //oops!!! + + //found an intersect node that can be swapped ... + SwapIntersectNodes(*int1, *int2); + e1 = int1->edge1; + e2 = int1->edge2; + } + SwapPositionsInSEL(e1, e2); + int1 = int1->next; + int2 = int1->next; + } + + m_SortedEdges = 0; + + //finally, check the last intersection too ... + return (int1->edge1->prevInSEL == int1->edge2 || + int1->edge1->nextInSEL == int1->edge2); +} +//------------------------------------------------------------------------------ + +bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) +{ + return e2.xcurr == e1.xcurr ? e2.dx > e1.dx : e2.xcurr < e1.xcurr; +} +//------------------------------------------------------------------------------ + +void Clipper::InsertEdgeIntoAEL(TEdge *edge) +{ + edge->prevInAEL = 0; + edge->nextInAEL = 0; + if( !m_ActiveEdges ) + { + m_ActiveEdges = edge; + } + else if( E2InsertsBeforeE1(*m_ActiveEdges, *edge) ) + { + edge->nextInAEL = m_ActiveEdges; + m_ActiveEdges->prevInAEL = edge; + m_ActiveEdges = edge; + } else + { + TEdge* e = m_ActiveEdges; + while( e->nextInAEL && !E2InsertsBeforeE1(*e->nextInAEL , *edge) ) + e = e->nextInAEL; + edge->nextInAEL = e->nextInAEL; + if( e->nextInAEL ) e->nextInAEL->prevInAEL = edge; + edge->prevInAEL = e; + e->nextInAEL = edge; + } +} +//---------------------------------------------------------------------- + +void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge1, pt); + SwapSides(*edge1, *edge2); + SwapPolyIndexes(*edge1, *edge2); +} +//---------------------------------------------------------------------- + +void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge2, pt); + SwapSides(*edge1, *edge2); + SwapPolyIndexes(*edge1, *edge2); +} +//---------------------------------------------------------------------- + +void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge1, pt); + AddOutPt(edge2, pt); + SwapSides( *edge1 , *edge2 ); + SwapPolyIndexes( *edge1 , *edge2 ); +} +//---------------------------------------------------------------------- + +void Clipper::CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2) +{ + //when a polygon is split into 2 polygons, make sure any holes the original + //polygon contained link to the correct polygon ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *orec = m_PolyOuts[i]; + if (orec->isHole && orec->bottomPt && orec->FirstLeft == outRec1 && + !PointInPolygon(orec->bottomPt->pt, outRec1->pts, m_UseFullRange)) + orec->FirstLeft = outRec2; + } +} +//---------------------------------------------------------------------- + +void Clipper::CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2) +{ + //if a hole is owned by outRec2 then make it owned by outRec1 ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + if (m_PolyOuts[i]->isHole && m_PolyOuts[i]->bottomPt && + m_PolyOuts[i]->FirstLeft == outRec2) + m_PolyOuts[i]->FirstLeft = outRec1; +} +//---------------------------------------------------------------------- + +void Clipper::JoinCommonEdges(bool fixHoleLinkages) +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + { + JoinRec* j = m_Joins[i]; + OutRec *outRec1 = m_PolyOuts[j->poly1Idx]; + OutPt *pp1a = outRec1->pts; + OutRec *outRec2 = m_PolyOuts[j->poly2Idx]; + OutPt *pp2a = outRec2->pts; + IntPoint pt1 = j->pt2a, pt2 = j->pt2b; + IntPoint pt3 = j->pt1a, pt4 = j->pt1b; + if (!FindSegment(pp1a, pt1, pt2)) continue; + if (j->poly1Idx == j->poly2Idx) + { + //we're searching the same polygon for overlapping segments so + //segment 2 mustn't be the same as segment 1 ... + pp2a = pp1a->next; + if (!FindSegment(pp2a, pt3, pt4) || (pp2a == pp1a)) continue; + } + else if (!FindSegment(pp2a, pt3, pt4)) continue; + + if (!GetOverlapSegment(pt1, pt2, pt3, pt4, pt1, pt2)) continue; + + OutPt *p1, *p2, *p3, *p4; + OutPt *prev = pp1a->prev; + //get p1 & p2 polypts - the overlap start & endpoints on poly1 + if (PointsEqual(pp1a->pt, pt1)) p1 = pp1a; + else if (PointsEqual(prev->pt, pt1)) p1 = prev; + else p1 = InsertPolyPtBetween(pp1a, prev, pt1); + + if (PointsEqual(pp1a->pt, pt2)) p2 = pp1a; + else if (PointsEqual(prev->pt, pt2)) p2 = prev; + else if ((p1 == pp1a) || (p1 == prev)) + p2 = InsertPolyPtBetween(pp1a, prev, pt2); + else if (Pt3IsBetweenPt1AndPt2(pp1a->pt, p1->pt, pt2)) + p2 = InsertPolyPtBetween(pp1a, p1, pt2); else + p2 = InsertPolyPtBetween(p1, prev, pt2); + + //get p3 & p4 polypts - the overlap start & endpoints on poly2 + prev = pp2a->prev; + if (PointsEqual(pp2a->pt, pt1)) p3 = pp2a; + else if (PointsEqual(prev->pt, pt1)) p3 = prev; + else p3 = InsertPolyPtBetween(pp2a, prev, pt1); + + if (PointsEqual(pp2a->pt, pt2)) p4 = pp2a; + else if (PointsEqual(prev->pt, pt2)) p4 = prev; + else if ((p3 == pp2a) || (p3 == prev)) + p4 = InsertPolyPtBetween(pp2a, prev, pt2); + else if (Pt3IsBetweenPt1AndPt2(pp2a->pt, p3->pt, pt2)) + p4 = InsertPolyPtBetween(pp2a, p3, pt2); else + p4 = InsertPolyPtBetween(p3, prev, pt2); + + //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... + if (p1->next == p2 && p3->prev == p4) + { + p1->next = p3; + p3->prev = p1; + p2->prev = p4; + p4->next = p2; + } + else if (p1->prev == p2 && p3->next == p4) + { + p1->prev = p3; + p3->next = p1; + p2->next = p4; + p4->prev = p2; + } + else + continue; //an orientation is probably wrong + + if (j->poly2Idx == j->poly1Idx) + { + //instead of joining two polygons, we've just created a new one by + //splitting one polygon into two. + outRec1->pts = GetBottomPt(p1); + outRec1->bottomPt = outRec1->pts; + outRec1->bottomPt->idx = outRec1->idx; + outRec2 = CreateOutRec(); + m_PolyOuts.push_back(outRec2); + outRec2->idx = (int)m_PolyOuts.size()-1; + j->poly2Idx = outRec2->idx; + outRec2->pts = GetBottomPt(p2); + outRec2->bottomPt = outRec2->pts; + outRec2->bottomPt->idx = outRec2->idx; + + if (PointInPolygon(outRec2->pts->pt, outRec1->pts, m_UseFullRange)) + { + //outRec2 is contained by outRec1 ... + outRec2->isHole = !outRec1->isHole; + outRec2->FirstLeft = outRec1; + if (outRec2->isHole == + (m_ReverseOutput ^ Orientation(outRec2, m_UseFullRange))) + ReversePolyPtLinks(*outRec2->pts); + } else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange)) + { + //outRec1 is contained by outRec2 ... + outRec2->isHole = outRec1->isHole; + outRec1->isHole = !outRec2->isHole; + outRec2->FirstLeft = outRec1->FirstLeft; + outRec1->FirstLeft = outRec2; + if (outRec1->isHole == + (m_ReverseOutput ^ Orientation(outRec1, m_UseFullRange))) + ReversePolyPtLinks(*outRec1->pts); + //make sure any contained holes now link to the correct polygon ... + if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); + } else + { + outRec2->isHole = outRec1->isHole; + outRec2->FirstLeft = outRec1->FirstLeft; + //make sure any contained holes now link to the correct polygon ... + if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); + } + + //now fixup any subsequent joins that match this polygon + for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) + { + JoinRec* j2 = m_Joins[k]; + if (j2->poly1Idx == j->poly1Idx && PointIsVertex(j2->pt1a, p2)) + j2->poly1Idx = j->poly2Idx; + if (j2->poly2Idx == j->poly1Idx && PointIsVertex(j2->pt2a, p2)) + j2->poly2Idx = j->poly2Idx; + } + + //now cleanup redundant edges too ... + FixupOutPolygon(*outRec1); + FixupOutPolygon(*outRec2); + + if (Orientation(outRec1, m_UseFullRange) != (Area(*outRec1, m_UseFullRange) > 0)) + DisposeBottomPt(*outRec1); + if (Orientation(outRec2, m_UseFullRange) != (Area(*outRec2, m_UseFullRange) > 0)) + DisposeBottomPt(*outRec2); + + } else + { + //joined 2 polygons together ... + + //make sure any holes contained by outRec2 now link to outRec1 ... + if (fixHoleLinkages) CheckHoleLinkages2(outRec1, outRec2); + + //now cleanup redundant edges too ... + FixupOutPolygon(*outRec1); + + if (outRec1->pts) + { + outRec1->isHole = !Orientation(outRec1, m_UseFullRange); + if (outRec1->isHole && !outRec1->FirstLeft) + outRec1->FirstLeft = outRec2->FirstLeft; + } + + //delete the obsolete pointer ... + int OKIdx = outRec1->idx; + int ObsoleteIdx = outRec2->idx; + outRec2->pts = 0; + outRec2->bottomPt = 0; + outRec2->AppendLink = outRec1; + + //now fixup any subsequent Joins that match this polygon + for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) + { + JoinRec* j2 = m_Joins[k]; + if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx; + if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx; + } + } + } +} +//------------------------------------------------------------------------------ + +void ReversePolygon(Polygon& p) +{ + std::reverse(p.begin(), p.end()); +} +//------------------------------------------------------------------------------ + +void ReversePolygons(Polygons& p) +{ + for (Polygons::size_type i = 0; i < p.size(); ++i) + ReversePolygon(p[i]); +} + +//------------------------------------------------------------------------------ +// OffsetPolygon functions ... +//------------------------------------------------------------------------------ + +struct DoublePoint +{ + double X; + double Y; + DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} +}; +//------------------------------------------------------------------------------ + +Polygon BuildArc(const IntPoint &pt, + const double a1, const double a2, const double r) +{ + long64 steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1))); + if (steps > 0x100000) steps = 0x100000; + int n = (unsigned)steps; + Polygon result(n); + double da = (a2 - a1) / (n -1); + double a = a1; + for (int i = 0; i < n; ++i) + { + result[i].X = pt.X + Round(std::cos(a)*r); + result[i].Y = pt.Y + Round(std::sin(a)*r); + a += da; + } + return result; +} +//------------------------------------------------------------------------------ + +DoublePoint GetUnitNormal( const IntPoint &pt1, const IntPoint &pt2) +{ + if(pt2.X == pt1.X && pt2.Y == pt1.Y) + return DoublePoint(0, 0); + + double dx = (double)(pt2.X - pt1.X); + double dy = (double)(pt2.Y - pt1.Y); + double f = 1 *1.0/ std::sqrt( dx*dx + dy*dy ); + dx *= f; + dy *= f; + return DoublePoint(dy, -dx); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +class PolyOffsetBuilder +{ +private: + Polygons m_p; + Polygon* m_curr_poly; + std::vector normals; + double m_delta, m_RMin, m_R; + size_t m_i, m_j, m_k; + static const int buffLength = 128; + JoinType m_jointype; + +public: + +PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys, + double delta, JoinType jointype, double MiterLimit) +{ + //nb precondition - out_polys != ptsin_polys + if (NEAR_ZERO(delta)) + { + out_polys = in_polys; + return; + } + + this->m_p = in_polys; + this->m_delta = delta; + this->m_jointype = jointype; + if (MiterLimit <= 1) MiterLimit = 1; + m_RMin = 2/(MiterLimit*MiterLimit); + + double deltaSq = delta*delta; + out_polys.clear(); + out_polys.resize(in_polys.size()); + for (m_i = 0; m_i < in_polys.size(); m_i++) + { + m_curr_poly = &out_polys[m_i]; + size_t len = in_polys[m_i].size(); + if (len > 1 && m_p[m_i][0].X == m_p[m_i][len - 1].X && + m_p[m_i][0].Y == m_p[m_i][len-1].Y) len--; + + //when 'shrinking' polygons - to minimize artefacts + //strip those polygons that have an area < pi * delta^2 ... + double a1 = Area(in_polys[m_i]); + if (delta < 0) { if (a1 > 0 && a1 < deltaSq *pi) len = 0; } + else if (a1 < 0 && -a1 < deltaSq *pi) len = 0; //holes have neg. area + + if (len == 0 || (len < 3 && delta <= 0)) + continue; + else if (len == 1) + { + Polygon arc; + arc = BuildArc(in_polys[m_i][len-1], 0, 2 * pi, delta); + out_polys[m_i] = arc; + continue; + } + + //build normals ... + normals.clear(); + normals.resize(len); + normals[len-1] = GetUnitNormal(in_polys[m_i][len-1], in_polys[m_i][0]); + for (m_j = 0; m_j < len -1; ++m_j) + normals[m_j] = GetUnitNormal(in_polys[m_i][m_j], in_polys[m_i][m_j+1]); + + m_k = len -1; + for (m_j = 0; m_j < len; ++m_j) + { + switch (jointype) + { + case jtMiter: + { + m_R = 1 + (normals[m_j].X*normals[m_k].X + + normals[m_j].Y*normals[m_k].Y); + if (m_R >= m_RMin) DoMiter(); else DoSquare(MiterLimit); + break; + } + case jtSquare: DoSquare(); break; + case jtRound: DoRound(); break; + } + m_k = m_j; + } + } + + //finally, clean up untidy corners using Clipper ... + Clipper clpr; + clpr.AddPolygons(out_polys, ptSubject); + if (delta > 0) + { + if (!clpr.Execute(ctUnion, out_polys, pftPositive, pftPositive)) + out_polys.clear(); + } + else + { + IntRect r = clpr.GetBounds(); + Polygon outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPolygon(outer, ptSubject); + if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative)) + { + out_polys.erase(out_polys.begin()); + ReversePolygons(out_polys); + + } else + out_polys.clear(); + } +} +//------------------------------------------------------------------------------ + +private: + +void AddPoint(const IntPoint& pt) +{ + Polygon::size_type len = m_curr_poly->size(); + if (len == m_curr_poly->capacity()) + m_curr_poly->reserve(len + buffLength); + m_curr_poly->push_back(pt); +} +//------------------------------------------------------------------------------ + +void DoSquare(double mul = 1.0) +{ + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) + { + double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); + double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X); + a1 = std::fabs(a2 - a1); + if (a1 > pi) a1 = pi * 2 - a1; + double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul); + pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx), + (long64)(pt1.Y + normals[m_k].X * dx)); + AddPoint(pt1); + pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx), + (long64)(pt2.Y -normals[m_j].X * dx)); + AddPoint(pt2); + } + else + { + AddPoint(pt1); + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); + } +} +//------------------------------------------------------------------------------ + +void DoMiter() +{ + if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) + { + double q = m_delta / m_R; + AddPoint(IntPoint((long64)Round(m_p[m_i][m_j].X + + (normals[m_k].X + normals[m_j].X) * q), + (long64)Round(m_p[m_i][m_j].Y + (normals[m_k].Y + normals[m_j].Y) * q))); + } + else + { + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * + m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * + m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + AddPoint(pt1); + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); + } +} +//------------------------------------------------------------------------------ + +void DoRound() +{ + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + AddPoint(pt1); + //round off reflex angles (ie > 180 deg) unless almost flat (ie < ~10deg). + if ((normals[m_k].X*normals[m_j].Y - normals[m_j].X*normals[m_k].Y) * m_delta >= 0) + { + if (normals[m_j].X * normals[m_k].X + normals[m_j].Y * normals[m_k].Y < 0.985) + { + double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); + double a2 = std::atan2(normals[m_j].Y, normals[m_j].X); + if (m_delta > 0 && a2 < a1) a2 += pi *2; + else if (m_delta < 0 && a2 > a1) a2 -= pi *2; + Polygon arc = BuildArc(m_p[m_i][m_j], a1, a2, m_delta); + for (Polygon::size_type m = 0; m < arc.size(); m++) + AddPoint(arc[m]); + } + } + else + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); +} +//-------------------------------------------------------------------------- + +}; //end PolyOffsetBuilder + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, + double delta, JoinType jointype, double MiterLimit) +{ + if (&out_polys == &in_polys) + { + Polygons poly2(in_polys); + PolyOffsetBuilder(poly2, out_polys, delta, jointype, MiterLimit); + } + else PolyOffsetBuilder(in_polys, out_polys, delta, jointype, MiterLimit); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType) +{ + Clipper c; + c.AddPolygon(in_poly, ptSubject); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType) +{ + Clipper c; + c.AddPolygons(in_polys, ptSubject); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(Polygons &polys, PolyFillType fillType) +{ + SimplifyPolygons(polys, polys, fillType); +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, IntPoint& p) +{ + s << p.X << ' ' << p.Y << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, Polygon &p) +{ + for (Polygon::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, Polygons &p) +{ + for (Polygons::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +} //ClipperLib namespace diff --git a/contrib/clipper/clipper.hpp b/contrib/clipper/clipper.hpp index 7cbe898df..f6f196d0d 100644 --- a/contrib/clipper/clipper.hpp +++ b/contrib/clipper/clipper.hpp @@ -1,306 +1,306 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 4.8.8 * -* Date : 30 August 2012 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2012 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -#ifndef clipper_hpp -#define clipper_hpp - -#include -#include -#include -#include -#include - -namespace ClipperLib { - -enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; -enum PolyType { ptSubject, ptClip }; -//By far the most widely used winding rules for polygon filling are -//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) -//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) -//see http://glprogramming.com/red/chapter11.html -enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; - -typedef signed long long long64; -typedef unsigned long long ulong64; - -struct IntPoint { -public: - long64 X; - long64 Y; - IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; - friend std::ostream& operator <<(std::ostream &s, IntPoint &p); -}; - -typedef std::vector< IntPoint > Polygon; -typedef std::vector< Polygon > Polygons; - -std::ostream& operator <<(std::ostream &s, Polygon &p); -std::ostream& operator <<(std::ostream &s, Polygons &p); - -struct ExPolygon { - Polygon outer; - Polygons holes; -}; -typedef std::vector< ExPolygon > ExPolygons; - -enum JoinType { jtSquare, jtRound, jtMiter }; - -bool Orientation(const Polygon &poly); -double Area(const Polygon &poly); -void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, - double delta, JoinType jointype = jtSquare, double MiterLimit = 2); -void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd); - -void ReversePolygon(Polygon& p); -void ReversePolygons(Polygons& p); - -//used internally ... -enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 }; -enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; - -struct TEdge { - long64 xbot; - long64 ybot; - long64 xcurr; - long64 ycurr; - long64 xtop; - long64 ytop; - double dx; - long64 tmpX; - PolyType polyType; - EdgeSide side; - int windDelta; //1 or -1 depending on winding direction - int windCnt; - int windCnt2; //winding count of the opposite polytype - int outIdx; - TEdge *next; - TEdge *prev; - TEdge *nextInLML; - TEdge *nextInAEL; - TEdge *prevInAEL; - TEdge *nextInSEL; - TEdge *prevInSEL; -}; - -struct IntersectNode { - TEdge *edge1; - TEdge *edge2; - IntPoint pt; - IntersectNode *next; -}; - -struct LocalMinima { - long64 Y; - TEdge *leftBound; - TEdge *rightBound; - LocalMinima *next; -}; - -struct Scanbeam { - long64 Y; - Scanbeam *next; -}; - -struct OutPt; //forward declaration - -struct OutRec { - int idx; - bool isHole; - OutRec *FirstLeft; - OutRec *AppendLink; - OutPt *pts; - OutPt *bottomPt; - OutPt *bottomFlag; - EdgeSide sides; -}; - -struct OutPt { - int idx; - IntPoint pt; - OutPt *next; - OutPt *prev; -}; - -struct JoinRec { - IntPoint pt1a; - IntPoint pt1b; - int poly1Idx; - IntPoint pt2a; - IntPoint pt2b; - int poly2Idx; -}; - -struct HorzJoinRec { - TEdge *edge; - int savedIdx; -}; - -struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; - -typedef std::vector < OutRec* > PolyOutList; -typedef std::vector < TEdge* > EdgeList; -typedef std::vector < JoinRec* > JoinList; -typedef std::vector < HorzJoinRec* > HorzJoinList; - -//ClipperBase is the ancestor to the Clipper class. It should not be -//instantiated directly. This class simply abstracts the conversion of sets of -//polygon coordinates into edge objects that are stored in a LocalMinima list. -class ClipperBase -{ -public: - ClipperBase(); - virtual ~ClipperBase(); - bool AddPolygon(const Polygon &pg, PolyType polyType); - bool AddPolygons( const Polygons &ppg, PolyType polyType); - virtual void Clear(); - IntRect GetBounds(); -protected: - void DisposeLocalMinimaList(); - TEdge* AddBoundsToLML(TEdge *e); - void PopLocalMinima(); - virtual void Reset(); - void InsertLocalMinima(LocalMinima *newLm); - LocalMinima *m_CurrentLM; - LocalMinima *m_MinimaList; - bool m_UseFullRange; - EdgeList m_edges; -}; - -class Clipper : public virtual ClipperBase -{ -public: - Clipper(); - ~Clipper(); - bool Execute(ClipType clipType, - Polygons &solution, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - bool Execute(ClipType clipType, - ExPolygons &solution, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - void Clear(); - bool ReverseSolution() {return m_ReverseOutput;}; - void ReverseSolution(bool value) {m_ReverseOutput = value;}; -protected: - void Reset(); - virtual bool ExecuteInternal(bool fixHoleLinkages); -private: - PolyOutList m_PolyOuts; - JoinList m_Joins; - HorzJoinList m_HorizJoins; - ClipType m_ClipType; - Scanbeam *m_Scanbeam; - TEdge *m_ActiveEdges; - TEdge *m_SortedEdges; - IntersectNode *m_IntersectNodes; - bool m_ExecuteLocked; - PolyFillType m_ClipFillType; - PolyFillType m_SubjFillType; - bool m_ReverseOutput; - void DisposeScanbeamList(); - void SetWindingCount(TEdge& edge); - bool IsEvenOddFillType(const TEdge& edge) const; - bool IsEvenOddAltFillType(const TEdge& edge) const; - void InsertScanbeam(const long64 Y); - long64 PopScanbeam(); - void InsertLocalMinimaIntoAEL(const long64 botY); - void InsertEdgeIntoAEL(TEdge *edge); - void AddEdgeToSEL(TEdge *edge); - void CopyAELToSEL(); - void DeleteFromSEL(TEdge *e); - void DeleteFromAEL(TEdge *e); - void UpdateEdgeIntoAEL(TEdge *&e); - void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); - bool IsContributing(const TEdge& edge) const; - bool IsTopHorz(const long64 XPos); - void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); - void DoMaxima(TEdge *e, long64 topY); - void ProcessHorizontals(); - void ProcessHorizontal(TEdge *horzEdge); - void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - void AppendPolygon(TEdge *e1, TEdge *e2); - void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void IntersectEdges(TEdge *e1, TEdge *e2, - const IntPoint &pt, IntersectProtects protects); - OutRec* CreateOutRec(); - void AddOutPt(TEdge *e, const IntPoint &pt); - void DisposeBottomPt(OutRec &outRec); - void DisposeAllPolyPts(); - void DisposeOutRec(PolyOutList::size_type index); - bool ProcessIntersections(const long64 botY, const long64 topY); - void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); - void BuildIntersectList(const long64 botY, const long64 topY); - void ProcessIntersectList(); - void ProcessEdgesAtTopOfScanbeam(const long64 topY); - void BuildResult(Polygons& polys); - void BuildResultEx(ExPolygons& polys); - void SetHoleState(TEdge *e, OutRec *OutRec); - void DisposeIntersectNodes(); - bool FixupIntersections(); - void FixupOutPolygon(OutRec &outRec); - bool IsHole(TEdge *e); - void FixHoleLinkage(OutRec *outRec); - void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); - void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); - void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); - void ClearJoins(); - void AddHorzJoin(TEdge *e, int idx); - void ClearHorzJoins(); - void JoinCommonEdges(bool fixHoleLinkages); -}; - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -class clipperException : public std::exception -{ - public: - clipperException(const char* description): m_descr(description) {} - virtual ~clipperException() throw() {} - virtual const char* what() const throw() {return m_descr.c_str();} - private: - std::string m_descr; -}; -//------------------------------------------------------------------------------ - -} //ClipperLib namespace - -#endif //clipper_hpp - - +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 4.8.8 * +* Date : 30 August 2012 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2012 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24–28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +#ifndef clipper_hpp +#define clipper_hpp + +#include +#include +#include +#include +#include + +namespace ClipperLib { + +enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; +enum PolyType { ptSubject, ptClip }; +//By far the most widely used winding rules for polygon filling are +//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) +//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) +//see http://glprogramming.com/red/chapter11.html +enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; + +typedef signed long long long64; +typedef unsigned long long ulong64; + +struct IntPoint { +public: + long64 X; + long64 Y; + IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; + friend std::ostream& operator <<(std::ostream &s, IntPoint &p); +}; + +typedef std::vector< IntPoint > Polygon; +typedef std::vector< Polygon > Polygons; + +std::ostream& operator <<(std::ostream &s, Polygon &p); +std::ostream& operator <<(std::ostream &s, Polygons &p); + +struct ExPolygon { + Polygon outer; + Polygons holes; +}; +typedef std::vector< ExPolygon > ExPolygons; + +enum JoinType { jtSquare, jtRound, jtMiter }; + +bool Orientation(const Polygon &poly); +double Area(const Polygon &poly); +void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, + double delta, JoinType jointype = jtSquare, double MiterLimit = 2); +void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd); + +void ReversePolygon(Polygon& p); +void ReversePolygons(Polygons& p); + +//used internally ... +enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 }; +enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; + +struct TEdge { + long64 xbot; + long64 ybot; + long64 xcurr; + long64 ycurr; + long64 xtop; + long64 ytop; + double dx; + long64 tmpX; + PolyType polyType; + EdgeSide side; + int windDelta; //1 or -1 depending on winding direction + int windCnt; + int windCnt2; //winding count of the opposite polytype + int outIdx; + TEdge *next; + TEdge *prev; + TEdge *nextInLML; + TEdge *nextInAEL; + TEdge *prevInAEL; + TEdge *nextInSEL; + TEdge *prevInSEL; +}; + +struct IntersectNode { + TEdge *edge1; + TEdge *edge2; + IntPoint pt; + IntersectNode *next; +}; + +struct LocalMinima { + long64 Y; + TEdge *leftBound; + TEdge *rightBound; + LocalMinima *next; +}; + +struct Scanbeam { + long64 Y; + Scanbeam *next; +}; + +struct OutPt; //forward declaration + +struct OutRec { + int idx; + bool isHole; + OutRec *FirstLeft; + OutRec *AppendLink; + OutPt *pts; + OutPt *bottomPt; + OutPt *bottomFlag; + EdgeSide sides; +}; + +struct OutPt { + int idx; + IntPoint pt; + OutPt *next; + OutPt *prev; +}; + +struct JoinRec { + IntPoint pt1a; + IntPoint pt1b; + int poly1Idx; + IntPoint pt2a; + IntPoint pt2b; + int poly2Idx; +}; + +struct HorzJoinRec { + TEdge *edge; + int savedIdx; +}; + +struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; + +typedef std::vector < OutRec* > PolyOutList; +typedef std::vector < TEdge* > EdgeList; +typedef std::vector < JoinRec* > JoinList; +typedef std::vector < HorzJoinRec* > HorzJoinList; + +//ClipperBase is the ancestor to the Clipper class. It should not be +//instantiated directly. This class simply abstracts the conversion of sets of +//polygon coordinates into edge objects that are stored in a LocalMinima list. +class ClipperBase +{ +public: + ClipperBase(); + virtual ~ClipperBase(); + bool AddPolygon(const Polygon &pg, PolyType polyType); + bool AddPolygons( const Polygons &ppg, PolyType polyType); + virtual void Clear(); + IntRect GetBounds(); +protected: + void DisposeLocalMinimaList(); + TEdge* AddBoundsToLML(TEdge *e); + void PopLocalMinima(); + virtual void Reset(); + void InsertLocalMinima(LocalMinima *newLm); + LocalMinima *m_CurrentLM; + LocalMinima *m_MinimaList; + bool m_UseFullRange; + EdgeList m_edges; +}; + +class Clipper : public virtual ClipperBase +{ +public: + Clipper(); + ~Clipper(); + bool Execute(ClipType clipType, + Polygons &solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + bool Execute(ClipType clipType, + ExPolygons &solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + void Clear(); + bool ReverseSolution() {return m_ReverseOutput;}; + void ReverseSolution(bool value) {m_ReverseOutput = value;}; +protected: + void Reset(); + virtual bool ExecuteInternal(bool fixHoleLinkages); +private: + PolyOutList m_PolyOuts; + JoinList m_Joins; + HorzJoinList m_HorizJoins; + ClipType m_ClipType; + Scanbeam *m_Scanbeam; + TEdge *m_ActiveEdges; + TEdge *m_SortedEdges; + IntersectNode *m_IntersectNodes; + bool m_ExecuteLocked; + PolyFillType m_ClipFillType; + PolyFillType m_SubjFillType; + bool m_ReverseOutput; + void DisposeScanbeamList(); + void SetWindingCount(TEdge& edge); + bool IsEvenOddFillType(const TEdge& edge) const; + bool IsEvenOddAltFillType(const TEdge& edge) const; + void InsertScanbeam(const long64 Y); + long64 PopScanbeam(); + void InsertLocalMinimaIntoAEL(const long64 botY); + void InsertEdgeIntoAEL(TEdge *edge); + void AddEdgeToSEL(TEdge *edge); + void CopyAELToSEL(); + void DeleteFromSEL(TEdge *e); + void DeleteFromAEL(TEdge *e); + void UpdateEdgeIntoAEL(TEdge *&e); + void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); + bool IsContributing(const TEdge& edge) const; + bool IsTopHorz(const long64 XPos); + void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); + void DoMaxima(TEdge *e, long64 topY); + void ProcessHorizontals(); + void ProcessHorizontal(TEdge *horzEdge); + void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + void AppendPolygon(TEdge *e1, TEdge *e2); + void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &pt, IntersectProtects protects); + OutRec* CreateOutRec(); + void AddOutPt(TEdge *e, const IntPoint &pt); + void DisposeBottomPt(OutRec &outRec); + void DisposeAllPolyPts(); + void DisposeOutRec(PolyOutList::size_type index); + bool ProcessIntersections(const long64 botY, const long64 topY); + void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); + void BuildIntersectList(const long64 botY, const long64 topY); + void ProcessIntersectList(); + void ProcessEdgesAtTopOfScanbeam(const long64 topY); + void BuildResult(Polygons& polys); + void BuildResultEx(ExPolygons& polys); + void SetHoleState(TEdge *e, OutRec *OutRec); + void DisposeIntersectNodes(); + bool FixupIntersections(); + void FixupOutPolygon(OutRec &outRec); + bool IsHole(TEdge *e); + void FixHoleLinkage(OutRec *outRec); + void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); + void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); + void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); + void ClearJoins(); + void AddHorzJoin(TEdge *e, int idx); + void ClearHorzJoins(); + void JoinCommonEdges(bool fixHoleLinkages); +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +class clipperException : public std::exception +{ + public: + clipperException(const char* description): m_descr(description) {} + virtual ~clipperException() throw() {} + virtual const char* what() const throw() {return m_descr.c_str();} + private: + std::string m_descr; +}; +//------------------------------------------------------------------------------ + +} //ClipperLib namespace + +#endif //clipper_hpp + + diff --git a/contrib/irrXML/CXMLReaderImpl.h b/contrib/irrXML/CXMLReaderImpl.h index d2472b28b..63b700dc1 100644 --- a/contrib/irrXML/CXMLReaderImpl.h +++ b/contrib/irrXML/CXMLReaderImpl.h @@ -1,809 +1,809 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h - -#ifndef __ICXML_READER_IMPL_H_INCLUDED__ -#define __ICXML_READER_IMPL_H_INCLUDED__ - -#include "irrXML.h" -#include "irrString.h" -#include "irrArray.h" - -using namespace Assimp; - -#ifdef _DEBUG -#define IRR_DEBUGPRINT(x) printf((x)); -#else // _DEBUG -#define IRR_DEBUGPRINT(x) -#endif // _DEBUG - - -namespace irr -{ -namespace io -{ - - -//! implementation of the IrrXMLReader -template -class CXMLReaderImpl : public IIrrXMLReader -{ -public: - - //! Constructor - CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) - : TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), - SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII) - { - if (!callback) - return; - - storeTargetFormat(); - - // read whole xml file - - readFile(callback); - - // clean up - - if (deleteCallBack) - delete callback; - - // create list with special characters - - createSpecialCharacterList(); - - // set pointer to text begin - P = TextBegin; - } - - - //! Destructor - virtual ~CXMLReaderImpl() - { - delete [] TextData; - } - - - //! Reads forward to the next xml node. - //! \return Returns false, if there was no further node. - virtual bool read() - { - // if not end reached, parse the node - if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0) - { - parseCurrentNode(); - return true; - } - - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return false; - } - - - //! Returns the type of the current XML node. - virtual EXML_NODE getNodeType() const - { - return CurrentNodeType; - } - - - //! Returns attribute count of the current XML node. - virtual int getAttributeCount() const - { - return Attributes.size(); - } - - - //! Returns name of an attribute. - virtual const char_type* getAttributeName(int idx) const - { - if (idx < 0 || idx >= (int)Attributes.size()) - return 0; - - return Attributes[idx].Name.c_str(); - } - - - //! Returns the value of an attribute. - virtual const char_type* getAttributeValue(int idx) const - { - if (idx < 0 || idx >= (int)Attributes.size()) - return 0; - - return Attributes[idx].Value.c_str(); - } - - - //! Returns the value of an attribute. - virtual const char_type* getAttributeValue(const char_type* name) const - { - const SAttribute* attr = getAttributeByName(name); - if (!attr) - return 0; - - return attr->Value.c_str(); - } - - - //! Returns the value of an attribute - virtual const char_type* getAttributeValueSafe(const char_type* name) const - { - const SAttribute* attr = getAttributeByName(name); - if (!attr) - return EmptyString.c_str(); - - return attr->Value.c_str(); - } - - - - //! Returns the value of an attribute as integer. - int getAttributeValueAsInt(const char_type* name) const - { - return (int)getAttributeValueAsFloat(name); - } - - - //! Returns the value of an attribute as integer. - int getAttributeValueAsInt(int idx) const - { - return (int)getAttributeValueAsFloat(idx); - } - - - //! Returns the value of an attribute as float. - float getAttributeValueAsFloat(const char_type* name) const - { - const SAttribute* attr = getAttributeByName(name); - if (!attr) - return 0; - - core::stringc c = attr->Value.c_str(); - return fast_atof(c.c_str()); - } - - - //! Returns the value of an attribute as float. - float getAttributeValueAsFloat(int idx) const - { - const char_type* attrvalue = getAttributeValue(idx); - if (!attrvalue) - return 0; - - core::stringc c = attrvalue; - return fast_atof(c.c_str()); - } - - - //! Returns the name of the current node. - virtual const char_type* getNodeName() const - { - return NodeName.c_str(); - } - - - //! Returns data of the current node. - virtual const char_type* getNodeData() const - { - return NodeName.c_str(); - } - - - //! Returns if an element is an empty element, like - virtual bool isEmptyElement() const - { - return IsEmptyElement; - } - - //! Returns format of the source xml file. - virtual ETEXT_FORMAT getSourceFormat() const - { - return SourceFormat; - } - - //! Returns format of the strings returned by the parser. - virtual ETEXT_FORMAT getParserFormat() const - { - return TargetFormat; - } - -private: - - // Reads the current xml node - void parseCurrentNode() - { - char_type* start = P; - - // move forward until '<' found - while(*P != L'<' && *P) - ++P; - - if (!*P) - return; - - if (P - start > 0) - { - // we found some text, store it - if (setText(start, P)) - return; - } - - ++P; - - // based on current token, parse and report next element - switch(*P) - { - case L'/': - parseClosingXMLElement(); - break; - case L'?': - ignoreDefinition(); - break; - case L'!': - if (!parseCDATA()) - parseComment(); - break; - default: - parseOpeningXMLElement(); - break; - } - } - - - //! sets the state that text was found. Returns true if set should be set - bool setText(char_type* start, char_type* end) - { - // check if text is more than 2 characters, and if not, check if there is - // only white space, so that this text won't be reported - if (end - start < 3) - { - char_type* p = start; - for(; p != end; ++p) - if (!isWhiteSpace(*p)) - break; - - if (p == end) - return false; - } - - // set current text to the parsed text, and replace xml special characters - core::string s(start, (int)(end - start)); - NodeName = replaceSpecialCharacters(s); - - // current XML node type is text - CurrentNodeType = EXN_TEXT; - - return true; - } - - - - //! ignores an xml definition like - void ignoreDefinition() - { - CurrentNodeType = EXN_UNKNOWN; - - // move until end marked with '>' reached - while(*P != L'>') - ++P; - - ++P; - } - - - //! parses a comment - void parseComment() - { - CurrentNodeType = EXN_COMMENT; - P += 1; - - char_type *pCommentBegin = P; - - int count = 1; - - // move until end of comment reached - while(count) - { - if (*P == L'>') - --count; - else - if (*P == L'<') - ++count; - - ++P; - } - - P -= 3; - NodeName = core::string(pCommentBegin+2, (int)(P - pCommentBegin-2)); - P += 3; - } - - - //! parses an opening xml element and reads attributes - void parseOpeningXMLElement() - { - CurrentNodeType = EXN_ELEMENT; - IsEmptyElement = false; - Attributes.clear(); - - // find name - const char_type* startName = P; - - // find end of element - while(*P != L'>' && !isWhiteSpace(*P)) - ++P; - - const char_type* endName = P; - - // find Attributes - while(*P != L'>') - { - if (isWhiteSpace(*P)) - ++P; - else - { - if (*P != L'/') - { - // we've got an attribute - - // read the attribute names - const char_type* attributeNameBegin = P; - - while(!isWhiteSpace(*P) && *P != L'=') - ++P; - - const char_type* attributeNameEnd = P; - ++P; - - // read the attribute value - // check for quotes and single quotes, thx to murphy - while( (*P != L'\"') && (*P != L'\'') && *P) - ++P; - - if (!*P) // malformatted xml file - return; - - const char_type attributeQuoteChar = *P; - - ++P; - const char_type* attributeValueBegin = P; - - while(*P != attributeQuoteChar && *P) - ++P; - - if (!*P) // malformatted xml file - return; - - const char_type* attributeValueEnd = P; - ++P; - - SAttribute attr; - attr.Name = core::string(attributeNameBegin, - (int)(attributeNameEnd - attributeNameBegin)); - - core::string s(attributeValueBegin, - (int)(attributeValueEnd - attributeValueBegin)); - - attr.Value = replaceSpecialCharacters(s); - Attributes.push_back(attr); - } - else - { - // tag is closed directly - ++P; - IsEmptyElement = true; - break; - } - } - } - - // check if this tag is closing directly - if (endName > startName && *(endName-1) == L'/') - { - // directly closing tag - IsEmptyElement = true; - endName--; - } - - NodeName = core::string(startName, (int)(endName - startName)); - - ++P; - } - - - //! parses an closing xml tag - void parseClosingXMLElement() - { - CurrentNodeType = EXN_ELEMENT_END; - IsEmptyElement = false; - Attributes.clear(); - - ++P; - const char_type* pBeginClose = P; - - while(*P != L'>') - ++P; - - // remove trailing whitespace, if any - while( isspace( P[-1])) - --P; - - NodeName = core::string(pBeginClose, (int)(P - pBeginClose)); - ++P; - } - - //! parses a possible CDATA section, returns false if begin was not a CDATA section - bool parseCDATA() - { - if (*(P+1) != L'[') - return false; - - CurrentNodeType = EXN_CDATA; - - // skip '' && - (*(P-1) == L']') && - (*(P-2) == L']')) - { - cDataEnd = P - 2; - } - - ++P; - } - - if ( cDataEnd ) - NodeName = core::string(cDataBegin, (int)(cDataEnd - cDataBegin)); - else - NodeName = ""; - - return true; - } - - - // structure for storing attribute-name pairs - struct SAttribute - { - core::string Name; - core::string Value; - }; - - // finds a current attribute by name, returns 0 if not found - const SAttribute* getAttributeByName(const char_type* name) const - { - if (!name) - return 0; - - core::string n = name; - - for (int i=0; i<(int)Attributes.size(); ++i) - if (Attributes[i].Name == n) - return &Attributes[i]; - - return 0; - } - - // replaces xml special characters in a string and creates a new one - core::string replaceSpecialCharacters( - core::string& origstr) - { - int pos = origstr.findFirst(L'&'); - int oldPos = 0; - - if (pos == -1) - return origstr; - - core::string newstr; - - while(pos != -1 && pos < origstr.size()-2) - { - // check if it is one of the special characters - - int specialChar = -1; - for (int i=0; i<(int)SpecialCharacters.size(); ++i) - { - const char_type* p = &origstr.c_str()[pos]+1; - - if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) - { - specialChar = i; - break; - } - } - - if (specialChar != -1) - { - newstr.append(origstr.subString(oldPos, pos - oldPos)); - newstr.append(SpecialCharacters[specialChar][0]); - pos += SpecialCharacters[specialChar].size(); - } - else - { - newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); - pos += 1; - } - - // find next & - oldPos = pos; - pos = origstr.findNext(L'&', pos); - } - - if (oldPos < origstr.size()-1) - newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); - - return newstr; - } - - - - //! reads the xml file and converts it into the wanted character format. - bool readFile(IFileReadCallBack* callback) - { - int size = callback->getSize(); - size += 4; // We need two terminating 0's at the end. - // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. - - char* data8 = new char[size]; - - if (!callback->read(data8, size-4)) - { - delete [] data8; - return false; - } - - // add zeros at end - - data8[size-1] = 0; - data8[size-2] = 0; - data8[size-3] = 0; - data8[size-4] = 0; - - char16* data16 = reinterpret_cast(data8); - char32* data32 = reinterpret_cast(data8); - - // now we need to convert the data to the desired target format - // based on the byte order mark. - - const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; - const int UTF16_BE = 0xFFFE; - const int UTF16_LE = 0xFEFF; - const int UTF32_BE = 0xFFFE0000; - const int UTF32_LE = 0x0000FEFF; - - // check source for all utf versions and convert to target data format - - if (size >= 4 && data32[0] == (char32)UTF32_BE) - { - // UTF-32, big endian - SourceFormat = ETF_UTF32_BE; - convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header - } - else - if (size >= 4 && data32[0] == (char32)UTF32_LE) - { - // UTF-32, little endian - SourceFormat = ETF_UTF32_LE; - convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header - } - else - if (size >= 2 && data16[0] == UTF16_BE) - { - // UTF-16, big endian - SourceFormat = ETF_UTF16_BE; - convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header - } - else - if (size >= 2 && data16[0] == UTF16_LE) - { - // UTF-16, little endian - SourceFormat = ETF_UTF16_LE; - convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header - } - else - if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2]) - { - // UTF-8 - SourceFormat = ETF_UTF8; - convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header - } - else - { - // ASCII - SourceFormat = ETF_ASCII; - convertTextData(data8, data8, size); - } - - return true; - } - - - //! converts the text file into the desired format. - //! \param source: begin of the text (without byte order mark) - //! \param pointerToStore: pointer to text data block which can be - //! stored or deleted based on the nesessary conversion. - //! \param sizeWithoutHeader: Text size in characters without header - template - void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) - { - // convert little to big endian if necessary - if (sizeof(src_char_type) > 1 && - isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) - convertToLittleEndian(source); - - // check if conversion is necessary: - if (sizeof(src_char_type) == sizeof(char_type)) - { - // no need to convert - TextBegin = (char_type*)source; - TextData = (char_type*)pointerToStore; - TextSize = sizeWithoutHeader; - } - else - { - // convert source into target data format. - // TODO: implement a real conversion. This one just - // copies bytes. This is a problem when there are - // unicode symbols using more than one character. - - TextData = new char_type[sizeWithoutHeader]; - - // MSVC debugger complains here about loss of data ... - - - // FIXME - gcc complains about 'shift width larger than width of type' - // for T == unsigned long. Avoid it by messing around volatile .. - volatile unsigned int c = 3; - const src_char_type cc = (src_char_type)((((uint64_t)1u << (sizeof( char_type)< - void convertToLittleEndian(src_char_type* t) - { - if (sizeof(src_char_type) == 4) - { - // 32 bit - - while(*t) - { - *t = ((*t & 0xff000000) >> 24) | - ((*t & 0x00ff0000) >> 8) | - ((*t & 0x0000ff00) << 8) | - ((*t & 0x000000ff) << 24); - ++t; - } - } - else - { - // 16 bit - - while(*t) - { - *t = (*t >> 8) | (*t << 8); - ++t; - } - } - } - - //! returns if a format is little endian - inline bool isLittleEndian(ETEXT_FORMAT f) - { - return f == ETF_ASCII || - f == ETF_UTF8 || - f == ETF_UTF16_LE || - f == ETF_UTF32_LE; - } - - - //! returns true if a character is whitespace - inline bool isWhiteSpace(char_type c) - { - return (c==' ' || c=='\t' || c=='\n' || c=='\r'); - } - - - //! generates a list with xml special characters - void createSpecialCharacterList() - { - // list of strings containing special symbols, - // the first character is the special character, - // the following is the symbol string without trailing &. - - SpecialCharacters.push_back("&"); - SpecialCharacters.push_back("gt;"); - SpecialCharacters.push_back("\"quot;"); - SpecialCharacters.push_back("'apos;"); - - } - - - //! compares the first n characters of the strings - bool equalsn(const char_type* str1, const char_type* str2, int len) - { - int i; - for(i=0; str1[i] && str2[i] && i < len; ++i) - if (str1[i] != str2[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same lenght - return (i == len) || (str1[i] == 0 && str2[i] == 0); - } - - - //! stores the target text format - void storeTargetFormat() - { - // get target format. We could have done this using template specialization, - // but VisualStudio 6 don't like it and we want to support it. - - switch(sizeof(char_type)) - { - case 1: - TargetFormat = ETF_UTF8; - break; - case 2: - TargetFormat = ETF_UTF16_LE; - break; - case 4: - TargetFormat = ETF_UTF32_LE; - break; - default: - TargetFormat = ETF_ASCII; // should never happen. - } - } - - - // instance variables: - - char_type* TextData; // data block of the text file - char_type* P; // current point in text to parse - char_type* TextBegin; // start of text to parse - unsigned int TextSize; // size of text to parse in characters, not bytes - - EXML_NODE CurrentNodeType; // type of the currently parsed node - ETEXT_FORMAT SourceFormat; // source format of the xml file - ETEXT_FORMAT TargetFormat; // output format of this parser - - core::string NodeName; // name of the node currently in - core::string EmptyString; // empty string to be returned by getSafe() methods - - bool IsEmptyElement; // is the currently parsed node empty? - - core::array< core::string > SpecialCharacters; // see createSpecialCharacterList() - - core::array Attributes; // attributes of current element - -}; // end CXMLReaderImpl - - -} // end namespace -} // end namespace - -#endif +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h + +#ifndef __ICXML_READER_IMPL_H_INCLUDED__ +#define __ICXML_READER_IMPL_H_INCLUDED__ + +#include "irrXML.h" +#include "irrString.h" +#include "irrArray.h" + +using namespace Assimp; + +#ifdef _DEBUG +#define IRR_DEBUGPRINT(x) printf((x)); +#else // _DEBUG +#define IRR_DEBUGPRINT(x) +#endif // _DEBUG + + +namespace irr +{ +namespace io +{ + + +//! implementation of the IrrXMLReader +template +class CXMLReaderImpl : public IIrrXMLReader +{ +public: + + //! Constructor + CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) + : TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), + SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII) + { + if (!callback) + return; + + storeTargetFormat(); + + // read whole xml file + + readFile(callback); + + // clean up + + if (deleteCallBack) + delete callback; + + // create list with special characters + + createSpecialCharacterList(); + + // set pointer to text begin + P = TextBegin; + } + + + //! Destructor + virtual ~CXMLReaderImpl() + { + delete [] TextData; + } + + + //! Reads forward to the next xml node. + //! \return Returns false, if there was no further node. + virtual bool read() + { + // if not end reached, parse the node + if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0) + { + parseCurrentNode(); + return true; + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + + //! Returns the type of the current XML node. + virtual EXML_NODE getNodeType() const + { + return CurrentNodeType; + } + + + //! Returns attribute count of the current XML node. + virtual int getAttributeCount() const + { + return Attributes.size(); + } + + + //! Returns name of an attribute. + virtual const char_type* getAttributeName(int idx) const + { + if (idx < 0 || idx >= (int)Attributes.size()) + return 0; + + return Attributes[idx].Name.c_str(); + } + + + //! Returns the value of an attribute. + virtual const char_type* getAttributeValue(int idx) const + { + if (idx < 0 || idx >= (int)Attributes.size()) + return 0; + + return Attributes[idx].Value.c_str(); + } + + + //! Returns the value of an attribute. + virtual const char_type* getAttributeValue(const char_type* name) const + { + const SAttribute* attr = getAttributeByName(name); + if (!attr) + return 0; + + return attr->Value.c_str(); + } + + + //! Returns the value of an attribute + virtual const char_type* getAttributeValueSafe(const char_type* name) const + { + const SAttribute* attr = getAttributeByName(name); + if (!attr) + return EmptyString.c_str(); + + return attr->Value.c_str(); + } + + + + //! Returns the value of an attribute as integer. + int getAttributeValueAsInt(const char_type* name) const + { + return (int)getAttributeValueAsFloat(name); + } + + + //! Returns the value of an attribute as integer. + int getAttributeValueAsInt(int idx) const + { + return (int)getAttributeValueAsFloat(idx); + } + + + //! Returns the value of an attribute as float. + float getAttributeValueAsFloat(const char_type* name) const + { + const SAttribute* attr = getAttributeByName(name); + if (!attr) + return 0; + + core::stringc c = attr->Value.c_str(); + return fast_atof(c.c_str()); + } + + + //! Returns the value of an attribute as float. + float getAttributeValueAsFloat(int idx) const + { + const char_type* attrvalue = getAttributeValue(idx); + if (!attrvalue) + return 0; + + core::stringc c = attrvalue; + return fast_atof(c.c_str()); + } + + + //! Returns the name of the current node. + virtual const char_type* getNodeName() const + { + return NodeName.c_str(); + } + + + //! Returns data of the current node. + virtual const char_type* getNodeData() const + { + return NodeName.c_str(); + } + + + //! Returns if an element is an empty element, like + virtual bool isEmptyElement() const + { + return IsEmptyElement; + } + + //! Returns format of the source xml file. + virtual ETEXT_FORMAT getSourceFormat() const + { + return SourceFormat; + } + + //! Returns format of the strings returned by the parser. + virtual ETEXT_FORMAT getParserFormat() const + { + return TargetFormat; + } + +private: + + // Reads the current xml node + void parseCurrentNode() + { + char_type* start = P; + + // move forward until '<' found + while(*P != L'<' && *P) + ++P; + + if (!*P) + return; + + if (P - start > 0) + { + // we found some text, store it + if (setText(start, P)) + return; + } + + ++P; + + // based on current token, parse and report next element + switch(*P) + { + case L'/': + parseClosingXMLElement(); + break; + case L'?': + ignoreDefinition(); + break; + case L'!': + if (!parseCDATA()) + parseComment(); + break; + default: + parseOpeningXMLElement(); + break; + } + } + + + //! sets the state that text was found. Returns true if set should be set + bool setText(char_type* start, char_type* end) + { + // check if text is more than 2 characters, and if not, check if there is + // only white space, so that this text won't be reported + if (end - start < 3) + { + char_type* p = start; + for(; p != end; ++p) + if (!isWhiteSpace(*p)) + break; + + if (p == end) + return false; + } + + // set current text to the parsed text, and replace xml special characters + core::string s(start, (int)(end - start)); + NodeName = replaceSpecialCharacters(s); + + // current XML node type is text + CurrentNodeType = EXN_TEXT; + + return true; + } + + + + //! ignores an xml definition like + void ignoreDefinition() + { + CurrentNodeType = EXN_UNKNOWN; + + // move until end marked with '>' reached + while(*P != L'>') + ++P; + + ++P; + } + + + //! parses a comment + void parseComment() + { + CurrentNodeType = EXN_COMMENT; + P += 1; + + char_type *pCommentBegin = P; + + int count = 1; + + // move until end of comment reached + while(count) + { + if (*P == L'>') + --count; + else + if (*P == L'<') + ++count; + + ++P; + } + + P -= 3; + NodeName = core::string(pCommentBegin+2, (int)(P - pCommentBegin-2)); + P += 3; + } + + + //! parses an opening xml element and reads attributes + void parseOpeningXMLElement() + { + CurrentNodeType = EXN_ELEMENT; + IsEmptyElement = false; + Attributes.clear(); + + // find name + const char_type* startName = P; + + // find end of element + while(*P != L'>' && !isWhiteSpace(*P)) + ++P; + + const char_type* endName = P; + + // find Attributes + while(*P != L'>') + { + if (isWhiteSpace(*P)) + ++P; + else + { + if (*P != L'/') + { + // we've got an attribute + + // read the attribute names + const char_type* attributeNameBegin = P; + + while(!isWhiteSpace(*P) && *P != L'=') + ++P; + + const char_type* attributeNameEnd = P; + ++P; + + // read the attribute value + // check for quotes and single quotes, thx to murphy + while( (*P != L'\"') && (*P != L'\'') && *P) + ++P; + + if (!*P) // malformatted xml file + return; + + const char_type attributeQuoteChar = *P; + + ++P; + const char_type* attributeValueBegin = P; + + while(*P != attributeQuoteChar && *P) + ++P; + + if (!*P) // malformatted xml file + return; + + const char_type* attributeValueEnd = P; + ++P; + + SAttribute attr; + attr.Name = core::string(attributeNameBegin, + (int)(attributeNameEnd - attributeNameBegin)); + + core::string s(attributeValueBegin, + (int)(attributeValueEnd - attributeValueBegin)); + + attr.Value = replaceSpecialCharacters(s); + Attributes.push_back(attr); + } + else + { + // tag is closed directly + ++P; + IsEmptyElement = true; + break; + } + } + } + + // check if this tag is closing directly + if (endName > startName && *(endName-1) == L'/') + { + // directly closing tag + IsEmptyElement = true; + endName--; + } + + NodeName = core::string(startName, (int)(endName - startName)); + + ++P; + } + + + //! parses an closing xml tag + void parseClosingXMLElement() + { + CurrentNodeType = EXN_ELEMENT_END; + IsEmptyElement = false; + Attributes.clear(); + + ++P; + const char_type* pBeginClose = P; + + while(*P != L'>') + ++P; + + // remove trailing whitespace, if any + while( isspace( P[-1])) + --P; + + NodeName = core::string(pBeginClose, (int)(P - pBeginClose)); + ++P; + } + + //! parses a possible CDATA section, returns false if begin was not a CDATA section + bool parseCDATA() + { + if (*(P+1) != L'[') + return false; + + CurrentNodeType = EXN_CDATA; + + // skip '' && + (*(P-1) == L']') && + (*(P-2) == L']')) + { + cDataEnd = P - 2; + } + + ++P; + } + + if ( cDataEnd ) + NodeName = core::string(cDataBegin, (int)(cDataEnd - cDataBegin)); + else + NodeName = ""; + + return true; + } + + + // structure for storing attribute-name pairs + struct SAttribute + { + core::string Name; + core::string Value; + }; + + // finds a current attribute by name, returns 0 if not found + const SAttribute* getAttributeByName(const char_type* name) const + { + if (!name) + return 0; + + core::string n = name; + + for (int i=0; i<(int)Attributes.size(); ++i) + if (Attributes[i].Name == n) + return &Attributes[i]; + + return 0; + } + + // replaces xml special characters in a string and creates a new one + core::string replaceSpecialCharacters( + core::string& origstr) + { + int pos = origstr.findFirst(L'&'); + int oldPos = 0; + + if (pos == -1) + return origstr; + + core::string newstr; + + while(pos != -1 && pos < origstr.size()-2) + { + // check if it is one of the special characters + + int specialChar = -1; + for (int i=0; i<(int)SpecialCharacters.size(); ++i) + { + const char_type* p = &origstr.c_str()[pos]+1; + + if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) + { + specialChar = i; + break; + } + } + + if (specialChar != -1) + { + newstr.append(origstr.subString(oldPos, pos - oldPos)); + newstr.append(SpecialCharacters[specialChar][0]); + pos += SpecialCharacters[specialChar].size(); + } + else + { + newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); + pos += 1; + } + + // find next & + oldPos = pos; + pos = origstr.findNext(L'&', pos); + } + + if (oldPos < origstr.size()-1) + newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); + + return newstr; + } + + + + //! reads the xml file and converts it into the wanted character format. + bool readFile(IFileReadCallBack* callback) + { + int size = callback->getSize(); + size += 4; // We need two terminating 0's at the end. + // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. + + char* data8 = new char[size]; + + if (!callback->read(data8, size-4)) + { + delete [] data8; + return false; + } + + // add zeros at end + + data8[size-1] = 0; + data8[size-2] = 0; + data8[size-3] = 0; + data8[size-4] = 0; + + char16* data16 = reinterpret_cast(data8); + char32* data32 = reinterpret_cast(data8); + + // now we need to convert the data to the desired target format + // based on the byte order mark. + + const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; + const int UTF16_BE = 0xFFFE; + const int UTF16_LE = 0xFEFF; + const int UTF32_BE = 0xFFFE0000; + const int UTF32_LE = 0x0000FEFF; + + // check source for all utf versions and convert to target data format + + if (size >= 4 && data32[0] == (char32)UTF32_BE) + { + // UTF-32, big endian + SourceFormat = ETF_UTF32_BE; + convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header + } + else + if (size >= 4 && data32[0] == (char32)UTF32_LE) + { + // UTF-32, little endian + SourceFormat = ETF_UTF32_LE; + convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header + } + else + if (size >= 2 && data16[0] == UTF16_BE) + { + // UTF-16, big endian + SourceFormat = ETF_UTF16_BE; + convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header + } + else + if (size >= 2 && data16[0] == UTF16_LE) + { + // UTF-16, little endian + SourceFormat = ETF_UTF16_LE; + convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header + } + else + if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2]) + { + // UTF-8 + SourceFormat = ETF_UTF8; + convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header + } + else + { + // ASCII + SourceFormat = ETF_ASCII; + convertTextData(data8, data8, size); + } + + return true; + } + + + //! converts the text file into the desired format. + //! \param source: begin of the text (without byte order mark) + //! \param pointerToStore: pointer to text data block which can be + //! stored or deleted based on the nesessary conversion. + //! \param sizeWithoutHeader: Text size in characters without header + template + void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) + { + // convert little to big endian if necessary + if (sizeof(src_char_type) > 1 && + isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) + convertToLittleEndian(source); + + // check if conversion is necessary: + if (sizeof(src_char_type) == sizeof(char_type)) + { + // no need to convert + TextBegin = (char_type*)source; + TextData = (char_type*)pointerToStore; + TextSize = sizeWithoutHeader; + } + else + { + // convert source into target data format. + // TODO: implement a real conversion. This one just + // copies bytes. This is a problem when there are + // unicode symbols using more than one character. + + TextData = new char_type[sizeWithoutHeader]; + + // MSVC debugger complains here about loss of data ... + + + // FIXME - gcc complains about 'shift width larger than width of type' + // for T == unsigned long. Avoid it by messing around volatile .. + volatile unsigned int c = 3; + const src_char_type cc = (src_char_type)((((uint64_t)1u << (sizeof( char_type)< + void convertToLittleEndian(src_char_type* t) + { + if (sizeof(src_char_type) == 4) + { + // 32 bit + + while(*t) + { + *t = ((*t & 0xff000000) >> 24) | + ((*t & 0x00ff0000) >> 8) | + ((*t & 0x0000ff00) << 8) | + ((*t & 0x000000ff) << 24); + ++t; + } + } + else + { + // 16 bit + + while(*t) + { + *t = (*t >> 8) | (*t << 8); + ++t; + } + } + } + + //! returns if a format is little endian + inline bool isLittleEndian(ETEXT_FORMAT f) + { + return f == ETF_ASCII || + f == ETF_UTF8 || + f == ETF_UTF16_LE || + f == ETF_UTF32_LE; + } + + + //! returns true if a character is whitespace + inline bool isWhiteSpace(char_type c) + { + return (c==' ' || c=='\t' || c=='\n' || c=='\r'); + } + + + //! generates a list with xml special characters + void createSpecialCharacterList() + { + // list of strings containing special symbols, + // the first character is the special character, + // the following is the symbol string without trailing &. + + SpecialCharacters.push_back("&"); + SpecialCharacters.push_back("gt;"); + SpecialCharacters.push_back("\"quot;"); + SpecialCharacters.push_back("'apos;"); + + } + + + //! compares the first n characters of the strings + bool equalsn(const char_type* str1, const char_type* str2, int len) + { + int i; + for(i=0; str1[i] && str2[i] && i < len; ++i) + if (str1[i] != str2[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same lenght + return (i == len) || (str1[i] == 0 && str2[i] == 0); + } + + + //! stores the target text format + void storeTargetFormat() + { + // get target format. We could have done this using template specialization, + // but VisualStudio 6 don't like it and we want to support it. + + switch(sizeof(char_type)) + { + case 1: + TargetFormat = ETF_UTF8; + break; + case 2: + TargetFormat = ETF_UTF16_LE; + break; + case 4: + TargetFormat = ETF_UTF32_LE; + break; + default: + TargetFormat = ETF_ASCII; // should never happen. + } + } + + + // instance variables: + + char_type* TextData; // data block of the text file + char_type* P; // current point in text to parse + char_type* TextBegin; // start of text to parse + unsigned int TextSize; // size of text to parse in characters, not bytes + + EXML_NODE CurrentNodeType; // type of the currently parsed node + ETEXT_FORMAT SourceFormat; // source format of the xml file + ETEXT_FORMAT TargetFormat; // output format of this parser + + core::string NodeName; // name of the node currently in + core::string EmptyString; // empty string to be returned by getSafe() methods + + bool IsEmptyElement; // is the currently parsed node empty? + + core::array< core::string > SpecialCharacters; // see createSpecialCharacterList() + + core::array Attributes; // attributes of current element + +}; // end CXMLReaderImpl + + +} // end namespace +} // end namespace + +#endif diff --git a/contrib/irrXML/heapsort.h b/contrib/irrXML/heapsort.h index 4395119df..d0db319d0 100644 --- a/contrib/irrXML/heapsort.h +++ b/contrib/irrXML/heapsort.h @@ -1,73 +1,73 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __IRR_HEAPSORT_H_INCLUDED__ -#define __IRR_HEAPSORT_H_INCLUDED__ - -#include "irrTypes.h" - -namespace irr -{ -namespace core -{ - -//! Sinks an element into the heap. -template -inline void heapsink(T*array, s32 element, s32 max) -{ - while ((element<<1) < max) // there is a left child - { - s32 j = (element<<1); - - if (j+1 < max && array[j] < array[j+1]) - j = j+1; // take right child - - if (array[element] < array[j]) - { - T t = array[j]; // swap elements - array[j] = array[element]; - array[element] = t; - element = j; - } - else - return; - } -} - - -//! Sorts an array with size 'size' using heapsort. -template -inline void heapsort(T* array_, s32 size) -{ - // for heapsink we pretent this is not c++, where - // arrays start with index 0. So we decrease the array pointer, - // the maximum always +2 and the element always +1 - - T* virtualArray = array_ - 1; - s32 virtualSize = size + 2; - s32 i; - - // build heap - - for (i=((size-1)/2); i>=0; --i) - heapsink(virtualArray, i+1, virtualSize-1); - - // sort array - - for (i=size-1; i>=0; --i) - { - T t = array_[0]; - array_[0] = array_[i]; - array_[i] = t; - heapsink(virtualArray, 1, i + 1); - } -} - -} // end namespace core -} // end namespace irr - - - -#endif - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_HEAPSORT_H_INCLUDED__ +#define __IRR_HEAPSORT_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace core +{ + +//! Sinks an element into the heap. +template +inline void heapsink(T*array, s32 element, s32 max) +{ + while ((element<<1) < max) // there is a left child + { + s32 j = (element<<1); + + if (j+1 < max && array[j] < array[j+1]) + j = j+1; // take right child + + if (array[element] < array[j]) + { + T t = array[j]; // swap elements + array[j] = array[element]; + array[element] = t; + element = j; + } + else + return; + } +} + + +//! Sorts an array with size 'size' using heapsort. +template +inline void heapsort(T* array_, s32 size) +{ + // for heapsink we pretent this is not c++, where + // arrays start with index 0. So we decrease the array pointer, + // the maximum always +2 and the element always +1 + + T* virtualArray = array_ - 1; + s32 virtualSize = size + 2; + s32 i; + + // build heap + + for (i=((size-1)/2); i>=0; --i) + heapsink(virtualArray, i+1, virtualSize-1); + + // sort array + + for (i=size-1; i>=0; --i) + { + T t = array_[0]; + array_[0] = array_[i]; + array_[i] = t; + heapsink(virtualArray, 1, i + 1); + } +} + +} // end namespace core +} // end namespace irr + + + +#endif + diff --git a/contrib/irrXML/irrArray.h b/contrib/irrXML/irrArray.h index 4bcf1fc11..40c822590 100644 --- a/contrib/irrXML/irrArray.h +++ b/contrib/irrXML/irrArray.h @@ -1,444 +1,444 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h - -#ifndef __IRR_ARRAY_H_INCLUDED__ -#define __IRR_ARRAY_H_INCLUDED__ - -#include "irrTypes.h" -#include "heapsort.h" - -namespace irr -{ -namespace core -{ - -//! Self reallocating template array (like stl vector) with additional features. -/** Some features are: Heap sorting, binary search methods, easier debugging. -*/ -template -class array -{ - -public: - - array() - : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) - { - } - - //! Constructs a array and allocates an initial chunk of memory. - //! \param start_count: Amount of elements to allocate. - array(u32 start_count) - : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) - { - reallocate(start_count); - } - - - //! Copy constructor - array(const array& other) - : data(0) - { - *this = other; - } - - - - //! Destructor. Frees allocated memory, if set_free_when_destroyed - //! was not set to false by the user before. - ~array() - { - if (free_when_destroyed) - delete [] data; - } - - - - //! Reallocates the array, make it bigger or smaller. - //! \param new_size: New size of array. - void reallocate(u32 new_size) - { - T* old_data = data; - - data = new T[new_size]; - allocated = new_size; - - s32 end = used < new_size ? used : new_size; - for (s32 i=0; i allocated) - { - // reallocate(used * 2 +1); - // this doesn't work if the element is in the same array. So - // we'll copy the element first to be sure we'll get no data - // corruption - - T e; - e = element; // copy element - reallocate(used * 2 +1); // increase data block - data[used++] = e; // push_back - is_sorted = false; - return; - } - - data[used++] = element; - is_sorted = false; - } - - - //! Adds an element at the front of the array. If the array is to small to - //! add this new element, the array is made bigger. Please note that this - //! is slow, because the whole array needs to be copied for this. - //! \param element: Element to add at the back of the array. - void push_front(const T& element) - { - if (used + 1 > allocated) - reallocate(used * 2 +1); - - for (int i=(int)used; i>0; --i) - data[i] = data[i-1]; - - data[0] = element; - is_sorted = false; - ++used; - } - - - //! Insert item into array at specified position. Please use this - //! only if you know what you are doing (possible performance loss). - //! The preferred method of adding elements should be push_back(). - //! \param element: Element to be inserted - //! \param index: Where position to insert the new element. - void insert(const T& element, u32 index=0) - { - _IRR_DEBUG_BREAK_IF(index>used) // access violation - - if (used + 1 > allocated) - reallocate(used * 2 +1); - - for (u32 i=used++; i>index; i--) - data[i] = data[i-1]; - - data[index] = element; - is_sorted = false; - } - - - - - //! Clears the array and deletes all allocated memory. - void clear() - { - delete [] data; - data = 0; - used = 0; - allocated = 0; - is_sorted = true; - } - - - - //! Sets pointer to new array, using this as new workspace. - //! \param newPointer: Pointer to new array of elements. - //! \param size: Size of the new array. - void set_pointer(T* newPointer, u32 size) - { - delete [] data; - data = newPointer; - allocated = size; - used = size; - is_sorted = false; - } - - - - //! Sets if the array should delete the memory it used. - //! \param f: If true, the array frees the allocated memory in its - //! destructor, otherwise not. The default is true. - void set_free_when_destroyed(bool f) - { - free_when_destroyed = f; - } - - - - //! Sets the size of the array. - //! \param usedNow: Amount of elements now used. - void set_used(u32 usedNow) - { - if (allocated < usedNow) - reallocate(usedNow); - - used = usedNow; - } - - - - //! Assignement operator - void operator=(const array& other) - { - if (data) - delete [] data; - - //if (allocated < other.allocated) - if (other.allocated == 0) - data = 0; - else - data = new T[other.allocated]; - - used = other.used; - free_when_destroyed = other.free_when_destroyed; - is_sorted = other.is_sorted; - allocated = other.allocated; - - for (u32 i=0; i=used) // access violation - - return data[index]; - } - - - - //! Direct access operator - const T& operator [](u32 index) const - { - _IRR_DEBUG_BREAK_IF(index>=used) // access violation - - return data[index]; - } - - //! Gets last frame - const T& getLast() const - { - _IRR_DEBUG_BREAK_IF(!used) // access violation - - return data[used-1]; - } - - //! Gets last frame - T& getLast() - { - _IRR_DEBUG_BREAK_IF(!used) // access violation - - return data[used-1]; - } - - - //! Returns a pointer to the array. - //! \return Pointer to the array. - T* pointer() - { - return data; - } - - - - //! Returns a const pointer to the array. - //! \return Pointer to the array. - const T* const_pointer() const - { - return data; - } - - - - //! Returns size of used array. - //! \return Size of elements in the array. - u32 size() const - { - return used; - } - - - - //! Returns amount memory allocated. - //! \return Returns amount of memory allocated. The amount of bytes - //! allocated would be allocated_size() * sizeof(ElementsUsed); - u32 allocated_size() const - { - return allocated; - } - - - - //! Returns true if array is empty - //! \return True if the array is empty, false if not. - bool empty() const - { - return used == 0; - } - - - - //! Sorts the array using heapsort. There is no additional memory waste and - //! the algorithm performs (O) n log n in worst case. - void sort() - { - if (is_sorted || used<2) - return; - - heapsort(data, used); - is_sorted = true; - } - - - - //! Performs a binary search for an element, returns -1 if not found. - //! The array will be sorted before the binary search if it is not - //! already sorted. - //! \param element: Element to search for. - //! \return Returns position of the searched element if it was found, - //! otherwise -1 is returned. - s32 binary_search(const T& element) - { - return binary_search(element, 0, used-1); - } - - - - //! Performs a binary search for an element, returns -1 if not found. - //! The array will be sorted before the binary search if it is not - //! already sorted. - //! \param element: Element to search for. - //! \param left: First left index - //! \param right: Last right index. - //! \return Returns position of the searched element if it was found, - //! otherwise -1 is returned. - s32 binary_search(const T& element, s32 left, s32 right) - { - if (!used) - return -1; - - sort(); - - s32 m; - - do - { - m = (left+right)>>1; - - if (element < data[m]) - right = m - 1; - else - left = m + 1; - - } while((element < data[m] || data[m] < element) && left<=right); - - // this last line equals to: - // " while((element != array[m]) && left<=right);" - // but we only want to use the '<' operator. - // the same in next line, it is "(element == array[m])" - - if (!(element < data[m]) && !(data[m] < element)) - return m; - - return -1; - } - - - //! Finds an element in linear time, which is very slow. Use - //! binary_search for faster finding. Only works if =operator is implemented. - //! \param element: Element to search for. - //! \return Returns position of the searched element if it was found, - //! otherwise -1 is returned. - s32 linear_search(T& element) - { - for (u32 i=0; i=0; --i) - if (data[i] == element) - return (s32)i; - - return -1; - } - - - - //! Erases an element from the array. May be slow, because all elements - //! following after the erased element have to be copied. - //! \param index: Index of element to be erased. - void erase(u32 index) - { - _IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation - - for (u32 i=index+1; i=used || index<0 || count<1 || index+count>used) // access violation - - for (u32 i=index+count; i +class array +{ + +public: + + array() + : data(0), allocated(0), used(0), + free_when_destroyed(true), is_sorted(true) + { + } + + //! Constructs a array and allocates an initial chunk of memory. + //! \param start_count: Amount of elements to allocate. + array(u32 start_count) + : data(0), allocated(0), used(0), + free_when_destroyed(true), is_sorted(true) + { + reallocate(start_count); + } + + + //! Copy constructor + array(const array& other) + : data(0) + { + *this = other; + } + + + + //! Destructor. Frees allocated memory, if set_free_when_destroyed + //! was not set to false by the user before. + ~array() + { + if (free_when_destroyed) + delete [] data; + } + + + + //! Reallocates the array, make it bigger or smaller. + //! \param new_size: New size of array. + void reallocate(u32 new_size) + { + T* old_data = data; + + data = new T[new_size]; + allocated = new_size; + + s32 end = used < new_size ? used : new_size; + for (s32 i=0; i allocated) + { + // reallocate(used * 2 +1); + // this doesn't work if the element is in the same array. So + // we'll copy the element first to be sure we'll get no data + // corruption + + T e; + e = element; // copy element + reallocate(used * 2 +1); // increase data block + data[used++] = e; // push_back + is_sorted = false; + return; + } + + data[used++] = element; + is_sorted = false; + } + + + //! Adds an element at the front of the array. If the array is to small to + //! add this new element, the array is made bigger. Please note that this + //! is slow, because the whole array needs to be copied for this. + //! \param element: Element to add at the back of the array. + void push_front(const T& element) + { + if (used + 1 > allocated) + reallocate(used * 2 +1); + + for (int i=(int)used; i>0; --i) + data[i] = data[i-1]; + + data[0] = element; + is_sorted = false; + ++used; + } + + + //! Insert item into array at specified position. Please use this + //! only if you know what you are doing (possible performance loss). + //! The preferred method of adding elements should be push_back(). + //! \param element: Element to be inserted + //! \param index: Where position to insert the new element. + void insert(const T& element, u32 index=0) + { + _IRR_DEBUG_BREAK_IF(index>used) // access violation + + if (used + 1 > allocated) + reallocate(used * 2 +1); + + for (u32 i=used++; i>index; i--) + data[i] = data[i-1]; + + data[index] = element; + is_sorted = false; + } + + + + + //! Clears the array and deletes all allocated memory. + void clear() + { + delete [] data; + data = 0; + used = 0; + allocated = 0; + is_sorted = true; + } + + + + //! Sets pointer to new array, using this as new workspace. + //! \param newPointer: Pointer to new array of elements. + //! \param size: Size of the new array. + void set_pointer(T* newPointer, u32 size) + { + delete [] data; + data = newPointer; + allocated = size; + used = size; + is_sorted = false; + } + + + + //! Sets if the array should delete the memory it used. + //! \param f: If true, the array frees the allocated memory in its + //! destructor, otherwise not. The default is true. + void set_free_when_destroyed(bool f) + { + free_when_destroyed = f; + } + + + + //! Sets the size of the array. + //! \param usedNow: Amount of elements now used. + void set_used(u32 usedNow) + { + if (allocated < usedNow) + reallocate(usedNow); + + used = usedNow; + } + + + + //! Assignement operator + void operator=(const array& other) + { + if (data) + delete [] data; + + //if (allocated < other.allocated) + if (other.allocated == 0) + data = 0; + else + data = new T[other.allocated]; + + used = other.used; + free_when_destroyed = other.free_when_destroyed; + is_sorted = other.is_sorted; + allocated = other.allocated; + + for (u32 i=0; i=used) // access violation + + return data[index]; + } + + + + //! Direct access operator + const T& operator [](u32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + return data[index]; + } + + //! Gets last frame + const T& getLast() const + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + //! Gets last frame + T& getLast() + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + + //! Returns a pointer to the array. + //! \return Pointer to the array. + T* pointer() + { + return data; + } + + + + //! Returns a const pointer to the array. + //! \return Pointer to the array. + const T* const_pointer() const + { + return data; + } + + + + //! Returns size of used array. + //! \return Size of elements in the array. + u32 size() const + { + return used; + } + + + + //! Returns amount memory allocated. + //! \return Returns amount of memory allocated. The amount of bytes + //! allocated would be allocated_size() * sizeof(ElementsUsed); + u32 allocated_size() const + { + return allocated; + } + + + + //! Returns true if array is empty + //! \return True if the array is empty, false if not. + bool empty() const + { + return used == 0; + } + + + + //! Sorts the array using heapsort. There is no additional memory waste and + //! the algorithm performs (O) n log n in worst case. + void sort() + { + if (is_sorted || used<2) + return; + + heapsort(data, used); + is_sorted = true; + } + + + + //! Performs a binary search for an element, returns -1 if not found. + //! The array will be sorted before the binary search if it is not + //! already sorted. + //! \param element: Element to search for. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 binary_search(const T& element) + { + return binary_search(element, 0, used-1); + } + + + + //! Performs a binary search for an element, returns -1 if not found. + //! The array will be sorted before the binary search if it is not + //! already sorted. + //! \param element: Element to search for. + //! \param left: First left index + //! \param right: Last right index. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 binary_search(const T& element, s32 left, s32 right) + { + if (!used) + return -1; + + sort(); + + s32 m; + + do + { + m = (left+right)>>1; + + if (element < data[m]) + right = m - 1; + else + left = m + 1; + + } while((element < data[m] || data[m] < element) && left<=right); + + // this last line equals to: + // " while((element != array[m]) && left<=right);" + // but we only want to use the '<' operator. + // the same in next line, it is "(element == array[m])" + + if (!(element < data[m]) && !(data[m] < element)) + return m; + + return -1; + } + + + //! Finds an element in linear time, which is very slow. Use + //! binary_search for faster finding. Only works if =operator is implemented. + //! \param element: Element to search for. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 linear_search(T& element) + { + for (u32 i=0; i=0; --i) + if (data[i] == element) + return (s32)i; + + return -1; + } + + + + //! Erases an element from the array. May be slow, because all elements + //! following after the erased element have to be copied. + //! \param index: Index of element to be erased. + void erase(u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation + + for (u32 i=index+1; i=used || index<0 || count<1 || index+count>used) // access violation + + for (u32 i=index+count; i and string work both with unicode AND ascii, -so you can assign unicode to string and ascii to string -(and the other way round) if your ever would want to. -Note that the conversation between both is not done using an encoding. - -Known bugs: -Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the -methods make_upper, make_lower and equals_ignore_case. -*/ -template -class string -{ -public: - - //! Default constructor - string() - : array(0), allocated(1), used(1) - { - array = new T[1]; - array[0] = 0x0; - } - - - - //! Constructor - string(const string& other) - : array(0), allocated(0), used(0) - { - *this = other; - } - - - //! Constructs a string from an int - string(int number) - : array(0), allocated(0), used(0) - { - // store if negative and make positive - - bool negative = false; - if (number < 0) - { - number *= -1; - negative = true; - } - - // temporary buffer for 16 numbers - - c8 tmpbuf[16]; - tmpbuf[15] = 0; - s32 idx = 15; - - // special case '0' - - if (!number) - { - tmpbuf[14] = '0'; - *this = &tmpbuf[14]; - return; - } - - // add numbers - - while(number && idx) - { - idx--; - tmpbuf[idx] = (c8)('0' + (number % 10)); - number = number / 10; - } - - // add sign - - if (negative) - { - idx--; - tmpbuf[idx] = '-'; - } - - *this = &tmpbuf[idx]; - } - - - - //! Constructor for copying a string from a pointer with a given lenght - template - string(const B* c, s32 lenght) - : array(0), allocated(0), used(0) - { - if (!c) - return; - - allocated = used = lenght+1; - array = new T[used]; - - for (s32 l = 0; l - string(const B* c) - : array(0),allocated(0), used(0) - { - *this = c; - } - - - - //! destructor - ~string() - { - delete [] array; - } - - - - //! Assignment operator - string& operator=(const string& other) - { - if (this == &other) - return *this; - - delete [] array; - allocated = used = other.size()+1; - array = new T[used]; - - const T* p = other.c_str(); - for (s32 i=0; i - string& operator=(const B* c) - { - if (!c) - { - if (!array) - { - array = new T[1]; - allocated = 1; - used = 1; - } - array[0] = 0x0; - return *this; - } - - if ((void*)c == (void*)array) - return *this; - - s32 len = 0; - const B* p = c; - while(*p) - { - ++len; - ++p; - } - - // we'll take the old string for a while, because the new string could be - // a part of the current string. - T* oldArray = array; - - allocated = used = len+1; - array = new T[used]; - - for (s32 l = 0; l operator+(const string& other) - { - string str(*this); - str.append(other); - - return str; - } - - //! Add operator for strings, ascii and unicode - template - string operator+(const B* c) - { - string str(*this); - str.append(c); - - return str; - } - - - - //! Direct access operator - T& operator [](const s32 index) const - { - _IRR_DEBUG_BREAK_IF(index>=used) // bad index - - return array[index]; - } - - - //! Comparison operator - bool operator ==(const T* str) const - { - int i; - for(i=0; array[i] && str[i]; ++i) - if (array[i] != str[i]) - return false; - - return !array[i] && !str[i]; - } - - - - //! Comparison operator - bool operator ==(const string& other) const - { - for(s32 i=0; array[i] && other.array[i]; ++i) - if (array[i] != other.array[i]) - return false; - - return used == other.used; - } - - - - //! Is smaller operator - bool operator <(const string& other) const - { - for(s32 i=0; array[i] && other.array[i]; ++i) - if (array[i] != other.array[i]) - return (array[i] < other.array[i]); - - return used < other.used; - } - - - - //! Equals not operator - bool operator !=(const string& other) const - { - return !(*this == other); - } - - - - //! Returns length of string - /** \return Returns length of the string in characters. */ - s32 size() const - { - return used-1; - } - - - - //! Returns character string - /** \return Returns pointer to C-style zero terminated string. */ - const T* c_str() const - { - return array; - } - - - - //! Makes the string lower case. - void make_lower() - { - const T A = (T)'A'; - const T Z = (T)'Z'; - const T diff = (T)'a' - A; - - for (s32 i=0; i=A && array[i]<=Z) - array[i] += diff; - } - } - - - - //! Makes the string upper case. - void make_upper() - { - const T a = (T)'a'; - const T z = (T)'z'; - const T diff = (T)'A' - a; - - for (s32 i=0; i=a && array[i]<=z) - array[i] += diff; - } - } - - - - //! Compares the string ignoring case. - /** \param other: Other string to compare. - \return Returns true if the string are equal ignoring case. */ - bool equals_ignore_case(const string& other) const - { - for(s32 i=0; array[i] && other[i]; ++i) - if (toLower(array[i]) != toLower(other[i])) - return false; - - return used == other.used; - } - - - //! compares the first n characters of the strings - bool equalsn(const string& other, int len) - { - int i; - for(i=0; array[i] && other[i] && i < len; ++i) - if (array[i] != other[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same lenght - return (i == len) || (used == other.used); - } - - - //! compares the first n characters of the strings - bool equalsn(const T* str, int len) - { - int i; - for(i=0; array[i] && str[i] && i < len; ++i) - if (array[i] != str[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same lenght - return (i == len) || (array[i] == 0 && str[i] == 0); - } - - - //! Appends a character to this string - /** \param character: Character to append. */ - void append(T character) - { - if (used + 1 > allocated) - reallocate((s32)used + 1); - - used += 1; - - array[used-2] = character; - array[used-1] = 0; - } - - //! Appends a string to this string - /** \param other: String to append. */ - void append(const string& other) - { - --used; - - s32 len = other.size(); - - if (used + len + 1 > allocated) - reallocate((s32)used + (s32)len + 1); - - for (s32 l=0; l& other, s32 length) - { - s32 len = other.size(); - - if (len < length) - { - append(other); - return; - } - - len = length; - --used; - - if (used + len > allocated) - reallocate((s32)used + (s32)len); - - for (s32 l=0; l - s32 findFirstCharNotInList(B* c, int count) const - { - for (int i=0; i - s32 findLastCharNotInList(B* c, int count) const - { - for (int i=used-2; i>=0; --i) - { - int j; - for (j=0; j=0; --i) - if (array[i] == c) - return i; - - return -1; - } - - - //! Returns a substring - //! \param begin: Start of substring. - //! \param length: Length of substring. - string subString(s32 begin, s32 length) - { - if (length <= 0) - return string(""); - - string o; - o.reserve(length+1); - - for (s32 i=0; i& other) - { - append(other); - } - - void operator += (int i) - { - append(string(i)); - } - - //! replaces all characters of a special type with another one - void replace(T toReplace, T replaceWith) - { - for (s32 i=0; i=used || index<0) // access violation - - for (int i=index+1; i=(T)'A' && t<=(T)'Z') - return t + ((T)'a' - (T)'A'); - else - return t; - } - - //! Reallocate the array, make it bigger or smaler - void reallocate(s32 new_size) - { - T* old_array = array; - - array = new T[new_size]; - allocated = new_size; - - s32 amount = used < new_size ? used : new_size; - for (s32 i=0; i stringc; - -//! Typedef for wide character strings -typedef string stringw; - -} // end namespace core -} // end namespace irr - -#endif - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_STRING_H_INCLUDED__ +#define __IRR_STRING_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace core +{ + +//! Very simple string class with some useful features. +/** string and string work both with unicode AND ascii, +so you can assign unicode to string and ascii to string +(and the other way round) if your ever would want to. +Note that the conversation between both is not done using an encoding. + +Known bugs: +Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the +methods make_upper, make_lower and equals_ignore_case. +*/ +template +class string +{ +public: + + //! Default constructor + string() + : array(0), allocated(1), used(1) + { + array = new T[1]; + array[0] = 0x0; + } + + + + //! Constructor + string(const string& other) + : array(0), allocated(0), used(0) + { + *this = other; + } + + + //! Constructs a string from an int + string(int number) + : array(0), allocated(0), used(0) + { + // store if negative and make positive + + bool negative = false; + if (number < 0) + { + number *= -1; + negative = true; + } + + // temporary buffer for 16 numbers + + c8 tmpbuf[16]; + tmpbuf[15] = 0; + s32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + idx--; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number = number / 10; + } + + // add sign + + if (negative) + { + idx--; + tmpbuf[idx] = '-'; + } + + *this = &tmpbuf[idx]; + } + + + + //! Constructor for copying a string from a pointer with a given lenght + template + string(const B* c, s32 lenght) + : array(0), allocated(0), used(0) + { + if (!c) + return; + + allocated = used = lenght+1; + array = new T[used]; + + for (s32 l = 0; l + string(const B* c) + : array(0),allocated(0), used(0) + { + *this = c; + } + + + + //! destructor + ~string() + { + delete [] array; + } + + + + //! Assignment operator + string& operator=(const string& other) + { + if (this == &other) + return *this; + + delete [] array; + allocated = used = other.size()+1; + array = new T[used]; + + const T* p = other.c_str(); + for (s32 i=0; i + string& operator=(const B* c) + { + if (!c) + { + if (!array) + { + array = new T[1]; + allocated = 1; + used = 1; + } + array[0] = 0x0; + return *this; + } + + if ((void*)c == (void*)array) + return *this; + + s32 len = 0; + const B* p = c; + while(*p) + { + ++len; + ++p; + } + + // we'll take the old string for a while, because the new string could be + // a part of the current string. + T* oldArray = array; + + allocated = used = len+1; + array = new T[used]; + + for (s32 l = 0; l operator+(const string& other) + { + string str(*this); + str.append(other); + + return str; + } + + //! Add operator for strings, ascii and unicode + template + string operator+(const B* c) + { + string str(*this); + str.append(c); + + return str; + } + + + + //! Direct access operator + T& operator [](const s32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // bad index + + return array[index]; + } + + + //! Comparison operator + bool operator ==(const T* str) const + { + int i; + for(i=0; array[i] && str[i]; ++i) + if (array[i] != str[i]) + return false; + + return !array[i] && !str[i]; + } + + + + //! Comparison operator + bool operator ==(const string& other) const + { + for(s32 i=0; array[i] && other.array[i]; ++i) + if (array[i] != other.array[i]) + return false; + + return used == other.used; + } + + + + //! Is smaller operator + bool operator <(const string& other) const + { + for(s32 i=0; array[i] && other.array[i]; ++i) + if (array[i] != other.array[i]) + return (array[i] < other.array[i]); + + return used < other.used; + } + + + + //! Equals not operator + bool operator !=(const string& other) const + { + return !(*this == other); + } + + + + //! Returns length of string + /** \return Returns length of the string in characters. */ + s32 size() const + { + return used-1; + } + + + + //! Returns character string + /** \return Returns pointer to C-style zero terminated string. */ + const T* c_str() const + { + return array; + } + + + + //! Makes the string lower case. + void make_lower() + { + const T A = (T)'A'; + const T Z = (T)'Z'; + const T diff = (T)'a' - A; + + for (s32 i=0; i=A && array[i]<=Z) + array[i] += diff; + } + } + + + + //! Makes the string upper case. + void make_upper() + { + const T a = (T)'a'; + const T z = (T)'z'; + const T diff = (T)'A' - a; + + for (s32 i=0; i=a && array[i]<=z) + array[i] += diff; + } + } + + + + //! Compares the string ignoring case. + /** \param other: Other string to compare. + \return Returns true if the string are equal ignoring case. */ + bool equals_ignore_case(const string& other) const + { + for(s32 i=0; array[i] && other[i]; ++i) + if (toLower(array[i]) != toLower(other[i])) + return false; + + return used == other.used; + } + + + //! compares the first n characters of the strings + bool equalsn(const string& other, int len) + { + int i; + for(i=0; array[i] && other[i] && i < len; ++i) + if (array[i] != other[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same lenght + return (i == len) || (used == other.used); + } + + + //! compares the first n characters of the strings + bool equalsn(const T* str, int len) + { + int i; + for(i=0; array[i] && str[i] && i < len; ++i) + if (array[i] != str[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same lenght + return (i == len) || (array[i] == 0 && str[i] == 0); + } + + + //! Appends a character to this string + /** \param character: Character to append. */ + void append(T character) + { + if (used + 1 > allocated) + reallocate((s32)used + 1); + + used += 1; + + array[used-2] = character; + array[used-1] = 0; + } + + //! Appends a string to this string + /** \param other: String to append. */ + void append(const string& other) + { + --used; + + s32 len = other.size(); + + if (used + len + 1 > allocated) + reallocate((s32)used + (s32)len + 1); + + for (s32 l=0; l& other, s32 length) + { + s32 len = other.size(); + + if (len < length) + { + append(other); + return; + } + + len = length; + --used; + + if (used + len > allocated) + reallocate((s32)used + (s32)len); + + for (s32 l=0; l + s32 findFirstCharNotInList(B* c, int count) const + { + for (int i=0; i + s32 findLastCharNotInList(B* c, int count) const + { + for (int i=used-2; i>=0; --i) + { + int j; + for (j=0; j=0; --i) + if (array[i] == c) + return i; + + return -1; + } + + + //! Returns a substring + //! \param begin: Start of substring. + //! \param length: Length of substring. + string subString(s32 begin, s32 length) + { + if (length <= 0) + return string(""); + + string o; + o.reserve(length+1); + + for (s32 i=0; i& other) + { + append(other); + } + + void operator += (int i) + { + append(string(i)); + } + + //! replaces all characters of a special type with another one + void replace(T toReplace, T replaceWith) + { + for (s32 i=0; i=used || index<0) // access violation + + for (int i=index+1; i=(T)'A' && t<=(T)'Z') + return t + ((T)'a' - (T)'A'); + else + return t; + } + + //! Reallocate the array, make it bigger or smaler + void reallocate(s32 new_size) + { + T* old_array = array; + + array = new T[new_size]; + allocated = new_size; + + s32 amount = used < new_size ? used : new_size; + for (s32 i=0; i stringc; + +//! Typedef for wide character strings +typedef string stringw; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/contrib/irrXML/irrTypes.h b/contrib/irrXML/irrTypes.h index f67be0657..a7f12ec75 100644 --- a/contrib/irrXML/irrTypes.h +++ b/contrib/irrXML/irrTypes.h @@ -1,108 +1,108 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __IRR_TYPES_H_INCLUDED__ -#define __IRR_TYPES_H_INCLUDED__ - -namespace irr -{ - -//! 8 bit unsigned variable. -/** This is a typedef for unsigned char, it ensures portability of the engine. */ -typedef unsigned char u8; - -//! 8 bit signed variable. -/** This is a typedef for signed char, it ensures portability of the engine. */ -typedef signed char s8; - -//! 8 bit character variable. -/** This is a typedef for char, it ensures portability of the engine. */ -typedef char c8; - - - -//! 16 bit unsigned variable. -/** This is a typedef for unsigned short, it ensures portability of the engine. */ -typedef unsigned short u16; - -//! 16 bit signed variable. -/** This is a typedef for signed short, it ensures portability of the engine. */ -typedef signed short s16; - - - -//! 32 bit unsigned variable. -/** This is a typedef for unsigned int, it ensures portability of the engine. */ -typedef unsigned int u32; - -//! 32 bit signed variable. -/** This is a typedef for signed int, it ensures portability of the engine. */ -typedef signed int s32; - - - -// 64 bit signed variable. -// This is a typedef for __int64, it ensures portability of the engine. -// This type is currently not used by the engine and not supported by compilers -// other than Microsoft Compilers, so it is outcommented. -//typedef __int64 s64; - - - -//! 32 bit floating point variable. -/** This is a typedef for float, it ensures portability of the engine. */ -typedef float f32; - -//! 64 bit floating point variable. -/** This is a typedef for double, it ensures portability of the engine. */ -typedef double f64; - - -} // end namespace - - -// define the wchar_t type if not already built in. -#ifdef _MSC_VER -#ifndef _WCHAR_T_DEFINED -//! A 16 bit wide character type. -/** - Defines the wchar_t-type. - In VS6, its not possible to tell - the standard compiler to treat wchar_t as a built-in type, and - sometimes we just don't want to include the huge stdlib.h or wchar.h, - so we'll use this. -*/ -typedef unsigned short wchar_t; -#define _WCHAR_T_DEFINED -#endif // wchar is not defined -#endif // microsoft compiler - -//! define a break macro for debugging only in Win32 mode. -// WORKAROUND (assimp): remove __asm -#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) -#if defined(_M_IX86) -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/ -#else -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) -#endif -#else -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) -#endif - -//! Defines a small statement to work around a microsoft compiler bug. -/** The microsft compiler 7.0 - 7.1 has a bug: -When you call unmanaged code that returns a bool type value of false from managed code, -the return value may appear as true. See -http://support.microsoft.com/default.aspx?kbid=823071 for details. -Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ - -// WORKAROUND (assimp): remove __asm -#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) -#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/ -#else -#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX -#endif // _IRR_MANAGED_MARSHALLING_BUGFIX - -#endif // __IRR_TYPES_H_INCLUDED__ - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_TYPES_H_INCLUDED__ +#define __IRR_TYPES_H_INCLUDED__ + +namespace irr +{ + +//! 8 bit unsigned variable. +/** This is a typedef for unsigned char, it ensures portability of the engine. */ +typedef unsigned char u8; + +//! 8 bit signed variable. +/** This is a typedef for signed char, it ensures portability of the engine. */ +typedef signed char s8; + +//! 8 bit character variable. +/** This is a typedef for char, it ensures portability of the engine. */ +typedef char c8; + + + +//! 16 bit unsigned variable. +/** This is a typedef for unsigned short, it ensures portability of the engine. */ +typedef unsigned short u16; + +//! 16 bit signed variable. +/** This is a typedef for signed short, it ensures portability of the engine. */ +typedef signed short s16; + + + +//! 32 bit unsigned variable. +/** This is a typedef for unsigned int, it ensures portability of the engine. */ +typedef unsigned int u32; + +//! 32 bit signed variable. +/** This is a typedef for signed int, it ensures portability of the engine. */ +typedef signed int s32; + + + +// 64 bit signed variable. +// This is a typedef for __int64, it ensures portability of the engine. +// This type is currently not used by the engine and not supported by compilers +// other than Microsoft Compilers, so it is outcommented. +//typedef __int64 s64; + + + +//! 32 bit floating point variable. +/** This is a typedef for float, it ensures portability of the engine. */ +typedef float f32; + +//! 64 bit floating point variable. +/** This is a typedef for double, it ensures portability of the engine. */ +typedef double f64; + + +} // end namespace + + +// define the wchar_t type if not already built in. +#ifdef _MSC_VER +#ifndef _WCHAR_T_DEFINED +//! A 16 bit wide character type. +/** + Defines the wchar_t-type. + In VS6, its not possible to tell + the standard compiler to treat wchar_t as a built-in type, and + sometimes we just don't want to include the huge stdlib.h or wchar.h, + so we'll use this. +*/ +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif // wchar is not defined +#endif // microsoft compiler + +//! define a break macro for debugging only in Win32 mode. +// WORKAROUND (assimp): remove __asm +#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) +#if defined(_M_IX86) +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/ +#else +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) +#endif +#else +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) +#endif + +//! Defines a small statement to work around a microsoft compiler bug. +/** The microsft compiler 7.0 - 7.1 has a bug: +When you call unmanaged code that returns a bool type value of false from managed code, +the return value may appear as true. See +http://support.microsoft.com/default.aspx?kbid=823071 for details. +Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ + +// WORKAROUND (assimp): remove __asm +#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/ +#else +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX +#endif // _IRR_MANAGED_MARSHALLING_BUGFIX + +#endif // __IRR_TYPES_H_INCLUDED__ + diff --git a/contrib/irrXML/irrXML.cpp b/contrib/irrXML/irrXML.cpp index eaaf2a264..42509b5f3 100644 --- a/contrib/irrXML/irrXML.cpp +++ b/contrib/irrXML/irrXML.cpp @@ -1,151 +1,151 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h - -// Need to include Assimp, too. We're using Assimp's version of fast_atof -// so we need stdint.h. But no PCH. - - -#include "irrXML.h" -#include "irrString.h" -#include "irrArray.h" -#include "./../../code/fast_atof.h" -#include "CXMLReaderImpl.h" - -namespace irr -{ -namespace io -{ - -//! Implementation of the file read callback for ordinary files -class CFileReadCallBack : public IFileReadCallBack -{ -public: - - //! construct from filename - CFileReadCallBack(const char* filename) - : File(0), Size(0), Close(true) - { - // open file - File = fopen(filename, "rb"); - - if (File) - getFileSize(); - } - - //! construct from FILE pointer - CFileReadCallBack(FILE* file) - : File(file), Size(0), Close(false) - { - if (File) - getFileSize(); - } - - //! destructor - virtual ~CFileReadCallBack() - { - if (Close && File) - fclose(File); - } - - //! Reads an amount of bytes from the file. - virtual int read(void* buffer, int sizeToRead) - { - if (!File) - return 0; - - return (int)fread(buffer, 1, sizeToRead, File); - } - - //! Returns size of file in bytes - virtual int getSize() - { - return Size; - } - -private: - - //! retrieves the file size of the open file - void getFileSize() - { - fseek(File, 0, SEEK_END); - Size = ftell(File); - fseek(File, 0, SEEK_SET); - } - - FILE* File; - int Size; - bool Close; - -}; // end class CFileReadCallBack - - - -// FACTORY FUNCTIONS: - - -//! Creates an instance of an UFT-8 or ASCII character xml parser. -IrrXMLReader* createIrrXMLReader(const char* filename) -{ - return new CXMLReaderImpl(new CFileReadCallBack(filename)); -} - - -//! Creates an instance of an UFT-8 or ASCII character xml parser. -IrrXMLReader* createIrrXMLReader(FILE* file) -{ - return new CXMLReaderImpl(new CFileReadCallBack(file)); -} - - -//! Creates an instance of an UFT-8 or ASCII character xml parser. -IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback) -{ - return new CXMLReaderImpl(callback, false); -} - - -//! Creates an instance of an UTF-16 xml parser. -IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename) -{ - return new CXMLReaderImpl(new CFileReadCallBack(filename)); -} - - -//! Creates an instance of an UTF-16 xml parser. -IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file) -{ - return new CXMLReaderImpl(new CFileReadCallBack(file)); -} - - -//! Creates an instance of an UTF-16 xml parser. -IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback) -{ - return new CXMLReaderImpl(callback, false); -} - - -//! Creates an instance of an UTF-32 xml parser. -IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename) -{ - return new CXMLReaderImpl(new CFileReadCallBack(filename)); -} - - -//! Creates an instance of an UTF-32 xml parser. -IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file) -{ - return new CXMLReaderImpl(new CFileReadCallBack(file)); -} - - -//! Creates an instance of an UTF-32 xml parser. -IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback) -{ - return new CXMLReaderImpl(callback, false); -} - - -} // end namespace io -} // end namespace irr +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h + +// Need to include Assimp, too. We're using Assimp's version of fast_atof +// so we need stdint.h. But no PCH. + + +#include "irrXML.h" +#include "irrString.h" +#include "irrArray.h" +#include "./../../code/fast_atof.h" +#include "CXMLReaderImpl.h" + +namespace irr +{ +namespace io +{ + +//! Implementation of the file read callback for ordinary files +class CFileReadCallBack : public IFileReadCallBack +{ +public: + + //! construct from filename + CFileReadCallBack(const char* filename) + : File(0), Size(0), Close(true) + { + // open file + File = fopen(filename, "rb"); + + if (File) + getFileSize(); + } + + //! construct from FILE pointer + CFileReadCallBack(FILE* file) + : File(file), Size(0), Close(false) + { + if (File) + getFileSize(); + } + + //! destructor + virtual ~CFileReadCallBack() + { + if (Close && File) + fclose(File); + } + + //! Reads an amount of bytes from the file. + virtual int read(void* buffer, int sizeToRead) + { + if (!File) + return 0; + + return (int)fread(buffer, 1, sizeToRead, File); + } + + //! Returns size of file in bytes + virtual int getSize() + { + return Size; + } + +private: + + //! retrieves the file size of the open file + void getFileSize() + { + fseek(File, 0, SEEK_END); + Size = ftell(File); + fseek(File, 0, SEEK_SET); + } + + FILE* File; + int Size; + bool Close; + +}; // end class CFileReadCallBack + + + +// FACTORY FUNCTIONS: + + +//! Creates an instance of an UFT-8 or ASCII character xml parser. +IrrXMLReader* createIrrXMLReader(const char* filename) +{ + return new CXMLReaderImpl(new CFileReadCallBack(filename)); +} + + +//! Creates an instance of an UFT-8 or ASCII character xml parser. +IrrXMLReader* createIrrXMLReader(FILE* file) +{ + return new CXMLReaderImpl(new CFileReadCallBack(file)); +} + + +//! Creates an instance of an UFT-8 or ASCII character xml parser. +IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback) +{ + return new CXMLReaderImpl(callback, false); +} + + +//! Creates an instance of an UTF-16 xml parser. +IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename) +{ + return new CXMLReaderImpl(new CFileReadCallBack(filename)); +} + + +//! Creates an instance of an UTF-16 xml parser. +IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file) +{ + return new CXMLReaderImpl(new CFileReadCallBack(file)); +} + + +//! Creates an instance of an UTF-16 xml parser. +IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback) +{ + return new CXMLReaderImpl(callback, false); +} + + +//! Creates an instance of an UTF-32 xml parser. +IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename) +{ + return new CXMLReaderImpl(new CFileReadCallBack(filename)); +} + + +//! Creates an instance of an UTF-32 xml parser. +IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file) +{ + return new CXMLReaderImpl(new CFileReadCallBack(file)); +} + + +//! Creates an instance of an UTF-32 xml parser. +IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback) +{ + return new CXMLReaderImpl(callback, false); +} + + +} // end namespace io +} // end namespace irr diff --git a/contrib/irrXML/irrXML.h b/contrib/irrXML/irrXML.h index f9badbd83..b51ddeb54 100644 --- a/contrib/irrXML/irrXML.h +++ b/contrib/irrXML/irrXML.h @@ -1,540 +1,540 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h - -#ifndef __IRR_XML_H_INCLUDED__ -#define __IRR_XML_H_INCLUDED__ - -#include - -/** \mainpage irrXML 1.2 API documentation -

- - \section intro Introduction - - Welcome to the irrXML API documentation. - Here you'll find any information you'll need to develop applications with - irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample, - at the homepage of irrXML at xml.irrlicht3d.org - or into the SDK in the directory \example. - - irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and - this documentation is an important part of it. If you have any questions or - suggestions, just send a email to the author of the engine, Nikolaus Gebhardt - (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history. - - \section features Features - - irrXML provides forward-only, read-only - access to a stream of non validated XML data. It was fully implemented by - Nikolaus Gebhardt. Its current features are: - - - It it fast as lighting and has very low memory usage. It was - developed with the intention of being used in 3D games, as it already has been. - - irrXML is very small: It only consists of 60 KB of code and can be added easily - to your existing project. - - Of course, it is platform independent and works with lots of compilers. - - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in - little and big endian format. - - Independent of the input file format, the parser can return all strings in ASCII, UTF-8, - UTF-16 and UTF-32 format. - - With its optional file access abstraction it has the advantage that it can read not - only from files but from any type of data (memory, network, ...). For example when - used with the Irrlicht Engine, it directly reads from compressed .zip files. - - Just like the Irrlicht Engine for which it was originally created, it is extremely easy - to use. - - It has no external dependencies, it does not even need the STL. - - Although irrXML has some strenghts, it currently also has the following limitations: - - - The input xml file is not validated and assumed to be correct. - - \section irrxmlexample Example - - The following code demonstrates the basic usage of irrXML. A simple xml - file like this is parsed: - \code - - - - - - Welcome to the Mesh Viewer of the "Irrlicht Engine". - - - \endcode - - The code for parsing this file would look like this: - \code - #include - using namespace irr; // irrXML is located in the namespace irr::io - using namespace io; - - #include // we use STL strings to store data in this example - - void main() - { - // create the reader using one of the factory functions - - IrrXMLReader* xml = createIrrXMLReader("config.xml"); - - // strings for storing the data we want to get out of the file - std::string modelFile; - std::string messageText; - std::string caption; - - // parse the file until end reached - - while(xml && xml->read()) - { - switch(xml->getNodeType()) - { - case EXN_TEXT: - // in this xml file, the only text which occurs is the messageText - messageText = xml->getNodeData(); - break; - case EXN_ELEMENT: - { - if (!strcmp("model", xml->getNodeName())) - modelFile = xml->getAttributeValue("file"); - else - if (!strcmp("messageText", xml->getNodeName())) - caption = xml->getAttributeValue("caption"); - } - break; - } - } - - // delete the xml parser after usage - delete xml; - } - \endcode - - \section howto How to use - - Simply add the source files in the /src directory of irrXML to your project. Done. - - \section license License - - The irrXML license is based on the zlib license. Basicly, this means you can do with - irrXML whatever you want: - - Copyright (C) 2002-2005 Nikolaus Gebhardt - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. - - \section history History - - As lots of references in this documentation and the source show, this xml - parser has originally been a part of the - Irrlicht Engine. But because - the parser has become very useful with the latest release, people asked for a - separate version of it, to be able to use it in non Irrlicht projects. With - irrXML 1.0, this has now been done. -*/ - -namespace irr -{ -namespace io -{ - //! Enumeration of all supported source text file formats - enum ETEXT_FORMAT - { - //! ASCII, file without byte order mark, or not a text file - ETF_ASCII, - - //! UTF-8 format - ETF_UTF8, - - //! UTF-16 format, big endian - ETF_UTF16_BE, - - //! UTF-16 format, little endian - ETF_UTF16_LE, - - //! UTF-32 format, big endian - ETF_UTF32_BE, - - //! UTF-32 format, little endian - ETF_UTF32_LE - }; - - - //! Enumeration for all xml nodes which are parsed by IrrXMLReader - enum EXML_NODE - { - //! No xml node. This is usually the node if you did not read anything yet. - EXN_NONE, - - //! A xml element, like - EXN_ELEMENT, - - //! End of an xml element, like - EXN_ELEMENT_END, - - //! Text within a xml element: this is the text. - EXN_TEXT, - - //! An xml comment like <!-- I am a comment --> or a DTD definition. - EXN_COMMENT, - - //! An xml cdata section like <![CDATA[ this is some CDATA ]]> - EXN_CDATA, - - //! Unknown element. - EXN_UNKNOWN - }; - - //! Callback class for file read abstraction. - /** With this, it is possible to make the xml parser read in other things - than just files. The Irrlicht engine is using this for example to - read xml from compressed .zip files. To make the parser read in - any other data, derive a class from this interface, implement the - two methods to read your data and give a pointer to an instance of - your implementation when calling createIrrXMLReader(), - createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */ - class IFileReadCallBack - { - public: - - //! virtual destructor - virtual ~IFileReadCallBack() {}; - - //! Reads an amount of bytes from the file. - /** \param buffer: Pointer to buffer where to read bytes will be written to. - \param sizeToRead: Amount of bytes to read from the file. - \return Returns how much bytes were read. */ - virtual int read(void* buffer, int sizeToRead) = 0; - - //! Returns size of file in bytes - virtual int getSize() = 0; - }; - - //! Empty class to be used as parent class for IrrXMLReader. - /** If you need another class as base class for the xml reader, you can do this by creating - the reader using for example new CXMLReaderImpl(yourcallback); - The Irrlicht Engine for example needs IUnknown as base class for every object to - let it automaticly reference countend, hence it replaces IXMLBase with IUnknown. - See irrXML.cpp on how this can be done in detail. */ - class IXMLBase - { - }; - - //! Interface providing easy read access to a XML file. - /** You can create an instance of this reader using one of the factory functions - createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32(). - If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() - instead. - For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features. - - The typical usage of this parser looks like this: - \code - #include - using namespace irr; // irrXML is located in the namespace irr::io - using namespace io; - - void main() - { - // create the reader using one of the factory functions - IrrXMLReader* xml = createIrrXMLReader("config.xml"); - - if (xml == 0) - return; // file could not be opened - - // parse the file until end reached - while(xml->read()) - { - // based on xml->getNodeType(), do something. - } - - // delete the xml parser after usage - delete xml; - } - \endcode - See \ref irrxmlexample for a more detailed example. - */ - template - class IIrrXMLReader : public super_class - { - public: - - //! Destructor - virtual ~IIrrXMLReader() {}; - - //! Reads forward to the next xml node. - /** \return Returns false, if there was no further node. */ - virtual bool read() = 0; - - //! Returns the type of the current XML node. - virtual EXML_NODE getNodeType() const = 0; - - //! Returns attribute count of the current XML node. - /** This is usually - non null if the current node is EXN_ELEMENT, and the element has attributes. - \return Returns amount of attributes of this xml node. */ - virtual int getAttributeCount() const = 0; - - //! Returns name of an attribute. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Name of the attribute, 0 if an attribute with this index does not exist. */ - virtual const char_type* getAttributeName(int idx) const = 0; - - //! Returns the value of an attribute. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Value of the attribute, 0 if an attribute with this index does not exist. */ - virtual const char_type* getAttributeValue(int idx) const = 0; - - //! Returns the value of an attribute. - /** \param name: Name of the attribute. - \return Value of the attribute, 0 if an attribute with this name does not exist. */ - virtual const char_type* getAttributeValue(const char_type* name) const = 0; - - //! Returns the value of an attribute in a safe way. - /** Like getAttributeValue(), but does not - return 0 if the attribute does not exist. An empty string ("") is returned then. - \param name: Name of the attribute. - \return Value of the attribute, and "" if an attribute with this name does not exist */ - virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0; - - //! Returns the value of an attribute as integer. - /** \param name Name of the attribute. - \return Value of the attribute as integer, and 0 if an attribute with this name does not exist or - the value could not be interpreted as integer. */ - virtual int getAttributeValueAsInt(const char_type* name) const = 0; - - //! Returns the value of an attribute as integer. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Value of the attribute as integer, and 0 if an attribute with this index does not exist or - the value could not be interpreted as integer. */ - virtual int getAttributeValueAsInt(int idx) const = 0; - - //! Returns the value of an attribute as float. - /** \param name: Name of the attribute. - \return Value of the attribute as float, and 0 if an attribute with this name does not exist or - the value could not be interpreted as float. */ - virtual float getAttributeValueAsFloat(const char_type* name) const = 0; - - //! Returns the value of an attribute as float. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Value of the attribute as float, and 0 if an attribute with this index does not exist or - the value could not be interpreted as float. */ - virtual float getAttributeValueAsFloat(int idx) const = 0; - - //! Returns the name of the current node. - /** Only non null, if the node type is EXN_ELEMENT. - \return Name of the current node or 0 if the node has no name. */ - virtual const char_type* getNodeName() const = 0; - - //! Returns data of the current node. - /** Only non null if the node has some - data and it is of type EXN_TEXT or EXN_UNKNOWN. */ - virtual const char_type* getNodeData() const = 0; - - //! Returns if an element is an empty element, like - virtual bool isEmptyElement() const = 0; - - //! Returns format of the source xml file. - /** It is not necessary to use - this method because the parser will convert the input file format - to the format wanted by the user when creating the parser. This - method is useful to get/display additional informations. */ - virtual ETEXT_FORMAT getSourceFormat() const = 0; - - //! Returns format of the strings returned by the parser. - /** This will be UTF8 for example when you created a parser with - IrrXMLReaderUTF8() and UTF32 when it has been created using - IrrXMLReaderUTF32. It should not be necessary to call this - method and only exists for informational purposes. */ - virtual ETEXT_FORMAT getParserFormat() const = 0; - }; - - - //! defines the utf-16 type. - /** Not using wchar_t for this because - wchar_t has 16 bit on windows and 32 bit on other operating systems. */ - typedef unsigned short char16; - - //! defines the utf-32 type. - /** Not using wchar_t for this because - wchar_t has 16 bit on windows and 32 bit on other operating systems. */ - typedef unsigned long char32; - - //! A UTF-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. - The file to read can be in any format, it will be converted to UTF-8 if it is not - in this format. - Create an instance of this with createIrrXMLReader(); - See IIrrXMLReader for description on how to use it. */ - typedef IIrrXMLReader IrrXMLReader; - - //! A UTF-16 xml parser. - /** This means that all character data will be returned in UTF-16 by this parser. - The file to read can be in any format, it will be converted to UTF-16 if it is not - in this format. - Create an instance of this with createIrrXMLReaderUTF16(); - See IIrrXMLReader for description on how to use it. */ - typedef IIrrXMLReader IrrXMLReaderUTF16; - - //! A UTF-32 xml parser. - /** This means that all character data will be returned in UTF-32 by this parser. - The file to read can be in any format, it will be converted to UTF-32 if it is not - in this format. - Create an instance of this with createIrrXMLReaderUTF32(); - See IIrrXMLReader for description on how to use it. */ - typedef IIrrXMLReader IrrXMLReaderUTF32; - - - //! Creates an instance of an UFT-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8. - The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReaderUTF8() instead. - \param filename: Name of file to be opened. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReader* createIrrXMLReader(const char* filename); - - //! Creates an instance of an UFT-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can - be in any format, it will be converted to UTF-8 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReaderUTF8() instead. - \param file: Pointer to opened file, must have been opened in binary mode, e.g. - using fopen("foo.bar", "wb"); The file will not be closed after it has been read. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReader* createIrrXMLReader(FILE* file); - - //! Creates an instance of an UFT-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can - be in any format, it will be converted to UTF-8 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReaderUTF8() instead. - \param callback: Callback for file read abstraction. Implement your own - callback to make the xml parser read in other things than just files. See - IFileReadCallBack for more information about this. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback); - - //! Creates an instance of an UFT-16 xml parser. - /** This means that - all character data will be returned in UTF-16. The file to read can - be in any format, it will be converted to UTF-16 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param filename: Name of file to be opened. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename); - - //! Creates an instance of an UFT-16 xml parser. - /** This means that all character data will be returned in UTF-16. The file to read can - be in any format, it will be converted to UTF-16 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param file: Pointer to opened file, must have been opened in binary mode, e.g. - using fopen("foo.bar", "wb"); The file will not be closed after it has been read. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file); - - //! Creates an instance of an UFT-16 xml parser. - /** This means that all character data will be returned in UTF-16. The file to read can - be in any format, it will be converted to UTF-16 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param callback: Callback for file read abstraction. Implement your own - callback to make the xml parser read in other things than just files. See - IFileReadCallBack for more information about this. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback); - - - //! Creates an instance of an UFT-32 xml parser. - /** This means that all character data will be returned in UTF-32. The file to read can - be in any format, it will be converted to UTF-32 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param filename: Name of file to be opened. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename); - - //! Creates an instance of an UFT-32 xml parser. - /** This means that all character data will be returned in UTF-32. The file to read can - be in any format, it will be converted to UTF-32 if it is not in this format. - if you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param file: Pointer to opened file, must have been opened in binary mode, e.g. - using fopen("foo.bar", "wb"); The file will not be closed after it has been read. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file); - - //! Creates an instance of an UFT-32 xml parser. - /** This means that - all character data will be returned in UTF-32. The file to read can - be in any format, it will be converted to UTF-32 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param callback: Callback for file read abstraction. Implement your own - callback to make the xml parser read in other things than just files. See - IFileReadCallBack for more information about this. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback); - - - /*! \file irrxml.h - \brief Header file of the irrXML, the Irrlicht XML parser. - - This file includes everything needed for using irrXML, - the XML parser of the Irrlicht Engine. To use irrXML, - you only need to include this file in your project: - - \code - #include - \endcode - - It is also common to use the two namespaces in which irrXML is included, - directly after #including irrXML.h: - - \code - #include - using namespace irr; - using namespace io; - \endcode - */ - -} // end namespace io -} // end namespace irr - -#endif // __IRR_XML_H_INCLUDED__ - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h + +#ifndef __IRR_XML_H_INCLUDED__ +#define __IRR_XML_H_INCLUDED__ + +#include + +/** \mainpage irrXML 1.2 API documentation +
+ + \section intro Introduction + + Welcome to the irrXML API documentation. + Here you'll find any information you'll need to develop applications with + irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample, + at the homepage of irrXML at xml.irrlicht3d.org + or into the SDK in the directory \example. + + irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and + this documentation is an important part of it. If you have any questions or + suggestions, just send a email to the author of the engine, Nikolaus Gebhardt + (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history. + + \section features Features + + irrXML provides forward-only, read-only + access to a stream of non validated XML data. It was fully implemented by + Nikolaus Gebhardt. Its current features are: + + - It it fast as lighting and has very low memory usage. It was + developed with the intention of being used in 3D games, as it already has been. + - irrXML is very small: It only consists of 60 KB of code and can be added easily + to your existing project. + - Of course, it is platform independent and works with lots of compilers. + - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in + little and big endian format. + - Independent of the input file format, the parser can return all strings in ASCII, UTF-8, + UTF-16 and UTF-32 format. + - With its optional file access abstraction it has the advantage that it can read not + only from files but from any type of data (memory, network, ...). For example when + used with the Irrlicht Engine, it directly reads from compressed .zip files. + - Just like the Irrlicht Engine for which it was originally created, it is extremely easy + to use. + - It has no external dependencies, it does not even need the STL. + + Although irrXML has some strenghts, it currently also has the following limitations: + + - The input xml file is not validated and assumed to be correct. + + \section irrxmlexample Example + + The following code demonstrates the basic usage of irrXML. A simple xml + file like this is parsed: + \code + + + + + + Welcome to the Mesh Viewer of the "Irrlicht Engine". + + + \endcode + + The code for parsing this file would look like this: + \code + #include + using namespace irr; // irrXML is located in the namespace irr::io + using namespace io; + + #include // we use STL strings to store data in this example + + void main() + { + // create the reader using one of the factory functions + + IrrXMLReader* xml = createIrrXMLReader("config.xml"); + + // strings for storing the data we want to get out of the file + std::string modelFile; + std::string messageText; + std::string caption; + + // parse the file until end reached + + while(xml && xml->read()) + { + switch(xml->getNodeType()) + { + case EXN_TEXT: + // in this xml file, the only text which occurs is the messageText + messageText = xml->getNodeData(); + break; + case EXN_ELEMENT: + { + if (!strcmp("model", xml->getNodeName())) + modelFile = xml->getAttributeValue("file"); + else + if (!strcmp("messageText", xml->getNodeName())) + caption = xml->getAttributeValue("caption"); + } + break; + } + } + + // delete the xml parser after usage + delete xml; + } + \endcode + + \section howto How to use + + Simply add the source files in the /src directory of irrXML to your project. Done. + + \section license License + + The irrXML license is based on the zlib license. Basicly, this means you can do with + irrXML whatever you want: + + Copyright (C) 2002-2005 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + \section history History + + As lots of references in this documentation and the source show, this xml + parser has originally been a part of the + Irrlicht Engine. But because + the parser has become very useful with the latest release, people asked for a + separate version of it, to be able to use it in non Irrlicht projects. With + irrXML 1.0, this has now been done. +*/ + +namespace irr +{ +namespace io +{ + //! Enumeration of all supported source text file formats + enum ETEXT_FORMAT + { + //! ASCII, file without byte order mark, or not a text file + ETF_ASCII, + + //! UTF-8 format + ETF_UTF8, + + //! UTF-16 format, big endian + ETF_UTF16_BE, + + //! UTF-16 format, little endian + ETF_UTF16_LE, + + //! UTF-32 format, big endian + ETF_UTF32_BE, + + //! UTF-32 format, little endian + ETF_UTF32_LE + }; + + + //! Enumeration for all xml nodes which are parsed by IrrXMLReader + enum EXML_NODE + { + //! No xml node. This is usually the node if you did not read anything yet. + EXN_NONE, + + //! A xml element, like + EXN_ELEMENT, + + //! End of an xml element, like + EXN_ELEMENT_END, + + //! Text within a xml element: this is the text. + EXN_TEXT, + + //! An xml comment like <!-- I am a comment --> or a DTD definition. + EXN_COMMENT, + + //! An xml cdata section like <![CDATA[ this is some CDATA ]]> + EXN_CDATA, + + //! Unknown element. + EXN_UNKNOWN + }; + + //! Callback class for file read abstraction. + /** With this, it is possible to make the xml parser read in other things + than just files. The Irrlicht engine is using this for example to + read xml from compressed .zip files. To make the parser read in + any other data, derive a class from this interface, implement the + two methods to read your data and give a pointer to an instance of + your implementation when calling createIrrXMLReader(), + createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */ + class IFileReadCallBack + { + public: + + //! virtual destructor + virtual ~IFileReadCallBack() {}; + + //! Reads an amount of bytes from the file. + /** \param buffer: Pointer to buffer where to read bytes will be written to. + \param sizeToRead: Amount of bytes to read from the file. + \return Returns how much bytes were read. */ + virtual int read(void* buffer, int sizeToRead) = 0; + + //! Returns size of file in bytes + virtual int getSize() = 0; + }; + + //! Empty class to be used as parent class for IrrXMLReader. + /** If you need another class as base class for the xml reader, you can do this by creating + the reader using for example new CXMLReaderImpl(yourcallback); + The Irrlicht Engine for example needs IUnknown as base class for every object to + let it automaticly reference countend, hence it replaces IXMLBase with IUnknown. + See irrXML.cpp on how this can be done in detail. */ + class IXMLBase + { + }; + + //! Interface providing easy read access to a XML file. + /** You can create an instance of this reader using one of the factory functions + createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32(). + If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() + instead. + For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features. + + The typical usage of this parser looks like this: + \code + #include + using namespace irr; // irrXML is located in the namespace irr::io + using namespace io; + + void main() + { + // create the reader using one of the factory functions + IrrXMLReader* xml = createIrrXMLReader("config.xml"); + + if (xml == 0) + return; // file could not be opened + + // parse the file until end reached + while(xml->read()) + { + // based on xml->getNodeType(), do something. + } + + // delete the xml parser after usage + delete xml; + } + \endcode + See \ref irrxmlexample for a more detailed example. + */ + template + class IIrrXMLReader : public super_class + { + public: + + //! Destructor + virtual ~IIrrXMLReader() {}; + + //! Reads forward to the next xml node. + /** \return Returns false, if there was no further node. */ + virtual bool read() = 0; + + //! Returns the type of the current XML node. + virtual EXML_NODE getNodeType() const = 0; + + //! Returns attribute count of the current XML node. + /** This is usually + non null if the current node is EXN_ELEMENT, and the element has attributes. + \return Returns amount of attributes of this xml node. */ + virtual int getAttributeCount() const = 0; + + //! Returns name of an attribute. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Name of the attribute, 0 if an attribute with this index does not exist. */ + virtual const char_type* getAttributeName(int idx) const = 0; + + //! Returns the value of an attribute. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute, 0 if an attribute with this index does not exist. */ + virtual const char_type* getAttributeValue(int idx) const = 0; + + //! Returns the value of an attribute. + /** \param name: Name of the attribute. + \return Value of the attribute, 0 if an attribute with this name does not exist. */ + virtual const char_type* getAttributeValue(const char_type* name) const = 0; + + //! Returns the value of an attribute in a safe way. + /** Like getAttributeValue(), but does not + return 0 if the attribute does not exist. An empty string ("") is returned then. + \param name: Name of the attribute. + \return Value of the attribute, and "" if an attribute with this name does not exist */ + virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0; + + //! Returns the value of an attribute as integer. + /** \param name Name of the attribute. + \return Value of the attribute as integer, and 0 if an attribute with this name does not exist or + the value could not be interpreted as integer. */ + virtual int getAttributeValueAsInt(const char_type* name) const = 0; + + //! Returns the value of an attribute as integer. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute as integer, and 0 if an attribute with this index does not exist or + the value could not be interpreted as integer. */ + virtual int getAttributeValueAsInt(int idx) const = 0; + + //! Returns the value of an attribute as float. + /** \param name: Name of the attribute. + \return Value of the attribute as float, and 0 if an attribute with this name does not exist or + the value could not be interpreted as float. */ + virtual float getAttributeValueAsFloat(const char_type* name) const = 0; + + //! Returns the value of an attribute as float. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute as float, and 0 if an attribute with this index does not exist or + the value could not be interpreted as float. */ + virtual float getAttributeValueAsFloat(int idx) const = 0; + + //! Returns the name of the current node. + /** Only non null, if the node type is EXN_ELEMENT. + \return Name of the current node or 0 if the node has no name. */ + virtual const char_type* getNodeName() const = 0; + + //! Returns data of the current node. + /** Only non null if the node has some + data and it is of type EXN_TEXT or EXN_UNKNOWN. */ + virtual const char_type* getNodeData() const = 0; + + //! Returns if an element is an empty element, like + virtual bool isEmptyElement() const = 0; + + //! Returns format of the source xml file. + /** It is not necessary to use + this method because the parser will convert the input file format + to the format wanted by the user when creating the parser. This + method is useful to get/display additional informations. */ + virtual ETEXT_FORMAT getSourceFormat() const = 0; + + //! Returns format of the strings returned by the parser. + /** This will be UTF8 for example when you created a parser with + IrrXMLReaderUTF8() and UTF32 when it has been created using + IrrXMLReaderUTF32. It should not be necessary to call this + method and only exists for informational purposes. */ + virtual ETEXT_FORMAT getParserFormat() const = 0; + }; + + + //! defines the utf-16 type. + /** Not using wchar_t for this because + wchar_t has 16 bit on windows and 32 bit on other operating systems. */ + typedef unsigned short char16; + + //! defines the utf-32 type. + /** Not using wchar_t for this because + wchar_t has 16 bit on windows and 32 bit on other operating systems. */ + typedef unsigned long char32; + + //! A UTF-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. + The file to read can be in any format, it will be converted to UTF-8 if it is not + in this format. + Create an instance of this with createIrrXMLReader(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReader; + + //! A UTF-16 xml parser. + /** This means that all character data will be returned in UTF-16 by this parser. + The file to read can be in any format, it will be converted to UTF-16 if it is not + in this format. + Create an instance of this with createIrrXMLReaderUTF16(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReaderUTF16; + + //! A UTF-32 xml parser. + /** This means that all character data will be returned in UTF-32 by this parser. + The file to read can be in any format, it will be converted to UTF-32 if it is not + in this format. + Create an instance of this with createIrrXMLReaderUTF32(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReaderUTF32; + + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. + The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReader* createIrrXMLReader(const char* filename); + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can + be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReader* createIrrXMLReader(FILE* file); + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can + be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that + all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback); + + + //! Creates an instance of an UFT-32 xml parser. + /** This means that all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename); + + //! Creates an instance of an UFT-32 xml parser. + /** This means that all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + if you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file); + + //! Creates an instance of an UFT-32 xml parser. + /** This means that + all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback); + + + /*! \file irrxml.h + \brief Header file of the irrXML, the Irrlicht XML parser. + + This file includes everything needed for using irrXML, + the XML parser of the Irrlicht Engine. To use irrXML, + you only need to include this file in your project: + + \code + #include + \endcode + + It is also common to use the two namespaces in which irrXML is included, + directly after #including irrXML.h: + + \code + #include + using namespace irr; + using namespace io; + \endcode + */ + +} // end namespace io +} // end namespace irr + +#endif // __IRR_XML_H_INCLUDED__ + diff --git a/contrib/irrXML_note.txt b/contrib/irrXML_note.txt index 403a0dbc6..ff7897ec2 100644 --- a/contrib/irrXML_note.txt +++ b/contrib/irrXML_note.txt @@ -1,6 +1,6 @@ - -IrrXML -Downloaded September 2008 - -- fixed a minor compiler warning (vs 2005, shift too large) -- fixed an issue regarding wchar_t/unsigned short + +IrrXML +Downloaded September 2008 + +- fixed a minor compiler warning (vs 2005, shift too large) +- fixed an issue regarding wchar_t/unsigned short diff --git a/contrib/poly2tri/poly2tri/common/utils.h b/contrib/poly2tri/poly2tri/common/utils.h index e3ed008f3..cb7a7dc01 100644 --- a/contrib/poly2tri/poly2tri/common/utils.h +++ b/contrib/poly2tri/poly2tri/common/utils.h @@ -1,105 +1,105 @@ -/* - * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors - * http://code.google.com/p/poly2tri/ - * - * All rights reserved. - * - * Redistribution and use 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 Poly2Tri nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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. - */ - -#ifndef UTILS_H -#define UTILS_H - -// Otherwise #defines like M_PI are undeclared under Visual Studio -#define _USE_MATH_DEFINES - -#include -#include - -namespace p2t { - -const double PI_3div4 = 3 * M_PI / 4; -const double EPSILON = 1e-15; - -enum Orientation { CW, CCW, COLLINEAR }; - -/** - * Forumla to calculate signed area
- * Positive if CCW
- * Negative if CW
- * 0 if collinear
- *
- * A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
- *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
- * 
- */ -Orientation Orient2d(Point& pa, Point& pb, Point& pc) -{ - double detleft = (pa.x - pc.x) * (pb.y - pc.y); - double detright = (pa.y - pc.y) * (pb.x - pc.x); - double val = detleft - detright; - if (val > -EPSILON && val < EPSILON) { - return COLLINEAR; - } else if (val > 0) { - return CCW; - } - return CW; -} - -bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) -{ - double pdx = pd.x; - double pdy = pd.y; - double adx = pa.x - pdx; - double ady = pa.y - pdy; - double bdx = pb.x - pdx; - double bdy = pb.y - pdy; - - double adxbdy = adx * bdy; - double bdxady = bdx * ady; - double oabd = adxbdy - bdxady; - - if (oabd <= EPSILON) { - return false; - } - - double cdx = pc.x - pdx; - double cdy = pc.y - pdy; - - double cdxady = cdx * ady; - double adxcdy = adx * cdy; - double ocad = cdxady - adxcdy; - - if (ocad <= EPSILON) { - return false; - } - - return true; -} - -} - -#endif - +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use 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 Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * 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. + */ + +#ifndef UTILS_H +#define UTILS_H + +// Otherwise #defines like M_PI are undeclared under Visual Studio +#define _USE_MATH_DEFINES + +#include +#include + +namespace p2t { + +const double PI_3div4 = 3 * M_PI / 4; +const double EPSILON = 1e-15; + +enum Orientation { CW, CCW, COLLINEAR }; + +/** + * Forumla to calculate signed area
+ * Positive if CCW
+ * Negative if CW
+ * 0 if collinear
+ *
+ * A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
+ *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
+ * 
+ */ +Orientation Orient2d(Point& pa, Point& pb, Point& pc) +{ + double detleft = (pa.x - pc.x) * (pb.y - pc.y); + double detright = (pa.y - pc.y) * (pb.x - pc.x); + double val = detleft - detright; + if (val > -EPSILON && val < EPSILON) { + return COLLINEAR; + } else if (val > 0) { + return CCW; + } + return CW; +} + +bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) +{ + double pdx = pd.x; + double pdy = pd.y; + double adx = pa.x - pdx; + double ady = pa.y - pdy; + double bdx = pb.x - pdx; + double bdy = pb.y - pdy; + + double adxbdy = adx * bdy; + double bdxady = bdx * ady; + double oabd = adxbdy - bdxady; + + if (oabd <= EPSILON) { + return false; + } + + double cdx = pc.x - pdx; + double cdy = pc.y - pdy; + + double cdxady = cdx * ady; + double adxcdy = adx * cdy; + double ocad = cdxady - adxcdy; + + if (ocad <= EPSILON) { + return false; + } + + return true; +} + +} + +#endif + diff --git a/contrib/poly2tri/poly2tri/sweep/cdt.h b/contrib/poly2tri/poly2tri/sweep/cdt.h index baf6ca7dd..3e6f02408 100644 --- a/contrib/poly2tri/poly2tri/sweep/cdt.h +++ b/contrib/poly2tri/poly2tri/sweep/cdt.h @@ -1,105 +1,105 @@ -/* - * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors - * http://code.google.com/p/poly2tri/ - * - * All rights reserved. - * - * Redistribution and use 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 Poly2Tri nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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. - */ - -#ifndef CDT_H -#define CDT_H - -#include "advancing_front.h" -#include "sweep_context.h" -#include "sweep.h" - -/** - * - * @author Mason Green - * - */ - -namespace p2t { - -class CDT -{ -public: - - /** - * Constructor - add polyline with non repeating points - * - * @param polyline - */ - CDT(std::vector polyline); - - /** - * Destructor - clean up memory - */ - ~CDT(); - - /** - * Add a hole - * - * @param polyline - */ - void AddHole(std::vector polyline); - - /** - * Add a steiner point - * - * @param point - */ - void AddPoint(Point* point); - - /** - * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points - */ - void Triangulate(); - - /** - * Get CDT triangles - */ - std::vector GetTriangles(); - - /** - * Get triangle map - */ - std::list GetMap(); - - private: - - /** - * Internals - */ - - SweepContext* sweep_context_; - Sweep* sweep_; - -}; - -} - -#endif +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use 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 Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * 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. + */ + +#ifndef CDT_H +#define CDT_H + +#include "advancing_front.h" +#include "sweep_context.h" +#include "sweep.h" + +/** + * + * @author Mason Green + * + */ + +namespace p2t { + +class CDT +{ +public: + + /** + * Constructor - add polyline with non repeating points + * + * @param polyline + */ + CDT(std::vector polyline); + + /** + * Destructor - clean up memory + */ + ~CDT(); + + /** + * Add a hole + * + * @param polyline + */ + void AddHole(std::vector polyline); + + /** + * Add a steiner point + * + * @param point + */ + void AddPoint(Point* point); + + /** + * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points + */ + void Triangulate(); + + /** + * Get CDT triangles + */ + std::vector GetTriangles(); + + /** + * Get triangle map + */ + std::list GetMap(); + + private: + + /** + * Internals + */ + + SweepContext* sweep_context_; + Sweep* sweep_; + +}; + +} + +#endif diff --git a/contrib/poly2tri/poly2tri/sweep/sweep_context.h b/contrib/poly2tri/poly2tri/sweep/sweep_context.h index 266408dc2..1010c0e8a 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep_context.h +++ b/contrib/poly2tri/poly2tri/sweep/sweep_context.h @@ -1,186 +1,186 @@ -/* - * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors - * http://code.google.com/p/poly2tri/ - * - * All rights reserved. - * - * Redistribution and use 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 Poly2Tri nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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. - */ - -#ifndef SWEEP_CONTEXT_H -#define SWEEP_CONTEXT_H - -#include -#include -#include - -namespace p2t { - -// Inital triangle factor, seed triangle will extend 30% of -// PointSet width to both left and right. -const double kAlpha = 0.3; - -struct Point; -class Triangle; -struct Node; -struct Edge; -class AdvancingFront; - -class SweepContext { -public: - -/// Constructor -SweepContext(std::vector polyline); -/// Destructor -~SweepContext(); - -void set_head(Point* p1); - -Point* head(); - -void set_tail(Point* p1); - -Point* tail(); - -int point_count(); - -Node& LocateNode(Point& point); - -void RemoveNode(Node* node); - -void CreateAdvancingFront(std::vector nodes); - -/// Try to map a node to all sides of this triangle that don't have a neighbor -void MapTriangleToNodes(Triangle& t); - -void AddToMap(Triangle* triangle); - -Point* GetPoint(const int& index); - -Point* GetPoints(); - -void RemoveFromMap(Triangle* triangle); - -void AddHole(std::vector polyline); - -void AddPoint(Point* point); - -AdvancingFront* front(); - -void MeshClean(Triangle& triangle); - -std::vector GetTriangles(); +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use 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 Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * 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. + */ + +#ifndef SWEEP_CONTEXT_H +#define SWEEP_CONTEXT_H + +#include +#include +#include + +namespace p2t { + +// Inital triangle factor, seed triangle will extend 30% of +// PointSet width to both left and right. +const double kAlpha = 0.3; + +struct Point; +class Triangle; +struct Node; +struct Edge; +class AdvancingFront; + +class SweepContext { +public: + +/// Constructor +SweepContext(std::vector polyline); +/// Destructor +~SweepContext(); + +void set_head(Point* p1); + +Point* head(); + +void set_tail(Point* p1); + +Point* tail(); + +int point_count(); + +Node& LocateNode(Point& point); + +void RemoveNode(Node* node); + +void CreateAdvancingFront(std::vector nodes); + +/// Try to map a node to all sides of this triangle that don't have a neighbor +void MapTriangleToNodes(Triangle& t); + +void AddToMap(Triangle* triangle); + +Point* GetPoint(const int& index); + +Point* GetPoints(); + +void RemoveFromMap(Triangle* triangle); + +void AddHole(std::vector polyline); + +void AddPoint(Point* point); + +AdvancingFront* front(); + +void MeshClean(Triangle& triangle); + +std::vector GetTriangles(); std::list GetMap(); - -std::vector edge_list; - -struct Basin { - Node* left_node; - Node* bottom_node; - Node* right_node; - double width; - bool left_highest; - - Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) - { - } - - void Clear() - { - left_node = NULL; - bottom_node = NULL; - right_node = NULL; - width = 0.0; - left_highest = false; - } -}; - -struct EdgeEvent { - Edge* constrained_edge; - bool right; - - EdgeEvent() : constrained_edge(NULL), right(false) - { - } -}; - -Basin basin; -EdgeEvent edge_event; - -private: - -friend class Sweep; - -std::vector triangles_; -std::list map_; -std::vector points_; - -// Advancing front -AdvancingFront* front_; -// head point used with advancing front -Point* head_; -// tail point used with advancing front -Point* tail_; - -Node *af_head_, *af_middle_, *af_tail_; - -void InitTriangulation(); -void InitEdges(std::vector polyline); - -}; - -inline AdvancingFront* SweepContext::front() -{ - return front_; -} - -inline int SweepContext::point_count() -{ - return points_.size(); -} - -inline void SweepContext::set_head(Point* p1) -{ - head_ = p1; -} - -inline Point* SweepContext::head() -{ - return head_; -} - -inline void SweepContext::set_tail(Point* p1) -{ - tail_ = p1; -} - -inline Point* SweepContext::tail() -{ - return tail_; -} - -} - -#endif + +std::vector edge_list; + +struct Basin { + Node* left_node; + Node* bottom_node; + Node* right_node; + double width; + bool left_highest; + + Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) + { + } + + void Clear() + { + left_node = NULL; + bottom_node = NULL; + right_node = NULL; + width = 0.0; + left_highest = false; + } +}; + +struct EdgeEvent { + Edge* constrained_edge; + bool right; + + EdgeEvent() : constrained_edge(NULL), right(false) + { + } +}; + +Basin basin; +EdgeEvent edge_event; + +private: + +friend class Sweep; + +std::vector triangles_; +std::list map_; +std::vector points_; + +// Advancing front +AdvancingFront* front_; +// head point used with advancing front +Point* head_; +// tail point used with advancing front +Point* tail_; + +Node *af_head_, *af_middle_, *af_tail_; + +void InitTriangulation(); +void InitEdges(std::vector polyline); + +}; + +inline AdvancingFront* SweepContext::front() +{ + return front_; +} + +inline int SweepContext::point_count() +{ + return points_.size(); +} + +inline void SweepContext::set_head(Point* p1) +{ + head_ = p1; +} + +inline Point* SweepContext::head() +{ + return head_; +} + +inline void SweepContext::set_tail(Point* p1) +{ + tail_ = p1; +} + +inline Point* SweepContext::tail() +{ + return tail_; +} + +} + +#endif diff --git a/contrib/poly2tri_patch.txt b/contrib/poly2tri_patch.txt index 33e621b20..e9cca4cec 100644 --- a/contrib/poly2tri_patch.txt +++ b/contrib/poly2tri_patch.txt @@ -1,75 +1,75 @@ -diff -r 5de9623d6a50 poly2tri/common/shapes.h ---- a/poly2tri/common/shapes.h Mon Aug 08 22:26:41 2011 -0400 -+++ b/poly2tri/common/shapes.h Tue Jan 17 02:36:52 2012 +0100 -@@ -35,6 +35,7 @@ - - #include - #include -+#include - #include - #include - -@@ -136,7 +137,9 @@ - p = &p2; - } else if (p1.x == p2.x) { - // Repeat points -- assert(false); -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("repeat points"); -+ //assert(false); - } - } - -diff -r 5de9623d6a50 poly2tri/sweep/sweep.cc ---- a/poly2tri/sweep/sweep.cc Mon Aug 08 22:26:41 2011 -0400 -+++ b/poly2tri/sweep/sweep.cc Tue Jan 17 02:36:52 2012 +0100 -@@ -113,6 +113,8 @@ - Point* p1 = triangle->PointCCW(point); - Orientation o1 = Orient2d(eq, *p1, ep); - if (o1 == COLLINEAR) { -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("EdgeEvent - collinear points not supported"); - if( triangle->Contains(&eq, p1)) { - triangle->MarkConstrainedEdge(&eq, p1 ); - // We are modifying the constraint maybe it would be better to -@@ -121,8 +123,8 @@ - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p1, triangle, *p1 ); - } else { -+ // ASSIMP_CHANGE (aramis_acg) - std::runtime_error("EdgeEvent - collinear points not supported"); -- assert(0); - } - return; - } -@@ -130,6 +132,9 @@ - Point* p2 = triangle->PointCW(point); - Orientation o2 = Orient2d(eq, *p2, ep); - if (o2 == COLLINEAR) { -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("EdgeEvent - collinear points not supported"); -+ - if( triangle->Contains(&eq, p2)) { - triangle->MarkConstrainedEdge(&eq, p2 ); - // We are modifying the constraint maybe it would be better to -@@ -138,8 +143,8 @@ - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p2, triangle, *p2 ); - } else { -- std::runtime_error("EdgeEvent - collinear points not supported"); -- assert(0); -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("EdgeEvent - collinear points not supported"); - } - return; - } -@@ -712,7 +717,8 @@ - return *ot.PointCW(op); - } else{ - //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); -- assert(0); -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); - } - } - +diff -r 5de9623d6a50 poly2tri/common/shapes.h +--- a/poly2tri/common/shapes.h Mon Aug 08 22:26:41 2011 -0400 ++++ b/poly2tri/common/shapes.h Tue Jan 17 02:36:52 2012 +0100 +@@ -35,6 +35,7 @@ + + #include + #include ++#include + #include + #include + +@@ -136,7 +137,9 @@ + p = &p2; + } else if (p1.x == p2.x) { + // Repeat points +- assert(false); ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("repeat points"); ++ //assert(false); + } + } + +diff -r 5de9623d6a50 poly2tri/sweep/sweep.cc +--- a/poly2tri/sweep/sweep.cc Mon Aug 08 22:26:41 2011 -0400 ++++ b/poly2tri/sweep/sweep.cc Tue Jan 17 02:36:52 2012 +0100 +@@ -113,6 +113,8 @@ + Point* p1 = triangle->PointCCW(point); + Orientation o1 = Orient2d(eq, *p1, ep); + if (o1 == COLLINEAR) { ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("EdgeEvent - collinear points not supported"); + if( triangle->Contains(&eq, p1)) { + triangle->MarkConstrainedEdge(&eq, p1 ); + // We are modifying the constraint maybe it would be better to +@@ -121,8 +123,8 @@ + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p1, triangle, *p1 ); + } else { ++ // ASSIMP_CHANGE (aramis_acg) + std::runtime_error("EdgeEvent - collinear points not supported"); +- assert(0); + } + return; + } +@@ -130,6 +132,9 @@ + Point* p2 = triangle->PointCW(point); + Orientation o2 = Orient2d(eq, *p2, ep); + if (o2 == COLLINEAR) { ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("EdgeEvent - collinear points not supported"); ++ + if( triangle->Contains(&eq, p2)) { + triangle->MarkConstrainedEdge(&eq, p2 ); + // We are modifying the constraint maybe it would be better to +@@ -138,8 +143,8 @@ + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p2, triangle, *p2 ); + } else { +- std::runtime_error("EdgeEvent - collinear points not supported"); +- assert(0); ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("EdgeEvent - collinear points not supported"); + } + return; + } +@@ -712,7 +717,8 @@ + return *ot.PointCW(op); + } else{ + //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); +- assert(0); ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); + } + } + diff --git a/contrib/unzip/crypt.h b/contrib/unzip/crypt.h index f14a628b4..622f4bc2e 100644 --- a/contrib/unzip/crypt.h +++ b/contrib/unzip/crypt.h @@ -1,132 +1,132 @@ -/* crypt.h -- base code for crypt/uncrypt ZIPfile - - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This code is a modified version of crypting code in Infozip distribution - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - If you don't need crypting in your application, just define symbols - NOCRYPT and NOUNCRYPT. - - This code support the "Traditional PKWARE Encryption". - - The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong - Encryption is not supported. -*/ - -#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) - -/*********************************************************************** - * Return the next byte in the pseudo-random sequence - */ -static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) -{ - unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an - * unpredictable manner on 16-bit systems; not a problem - * with any known compiler so far, though */ - - temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; - return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -/*********************************************************************** - * Update the encryption keys with the next byte of plain text - */ -static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) -{ - (*(pkeys+0)) = CRC32((*(pkeys+0)), c); - (*(pkeys+1)) += (*(pkeys+0)) & 0xff; - (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; - { - register int keyshift = (int)((*(pkeys+1)) >> 24); - (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); - } - return c; -} - - -/*********************************************************************** - * Initialize the encryption keys and the random header according to - * the given password. - */ -static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) -{ - *(pkeys+0) = 305419896L; - *(pkeys+1) = 591751049L; - *(pkeys+2) = 878082192L; - while (*passwd != '\0') { - update_keys(pkeys,pcrc_32_tab,(int)*passwd); - passwd++; - } -} - -#define zdecode(pkeys,pcrc_32_tab,c) \ - (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) - -#define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) - -#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED - -#define RAND_HEAD_LEN 12 - /* "last resort" source for second part of crypt seed pattern */ -# ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ -# endif - -static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) - const char *passwd; /* password string */ - unsigned char *buf; /* where to write header */ - int bufSize; - unsigned long* pkeys; - const unsigned long* pcrc_32_tab; - unsigned long crcForCrypting; -{ - int n; /* index in random header */ - int t; /* temporary */ - int c; /* random byte */ - unsigned char header[RAND_HEAD_LEN-2]; /* random header */ - static unsigned calls = 0; /* ensure different random header each time */ - - if (bufSize> 7) & 0xff; - header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); - } - /* Encrypt random header (last two bytes is high word of crc) */ - init_keys(passwd, pkeys, pcrc_32_tab); - for (n = 0; n < RAND_HEAD_LEN-2; n++) - { - buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); - } - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); - return n; -} - -#endif +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/contrib/unzip/ioapi.c b/contrib/unzip/ioapi.c index 44a9e11a3..b7200df75 100644 --- a/contrib/unzip/ioapi.c +++ b/contrib/unzip/ioapi.c @@ -1,181 +1,181 @@ -/* ioapi.c -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#include -#include -#include - -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../zlib/zlib.h" -# endif -#include "ioapi.h" - - - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -voidpf ZCALLBACK fopen_file_func ( - voidpf opaque, - const char* filename, - int mode); - -uLong ZCALLBACK fread_file_func ( - voidpf opaque, - voidpf stream, - void* buf, - uLong size); - -uLong ZCALLBACK fwrite_file_func ( - voidpf opaque, - voidpf stream, - const void* buf, - uLong size); - -long ZCALLBACK ftell_file_func ( - voidpf opaque, - voidpf stream); - -long ZCALLBACK fseek_file_func ( - voidpf opaque, - voidpf stream, - uLong offset, - int origin); - -int ZCALLBACK fclose_file_func ( - voidpf opaque, - voidpf stream); - -int ZCALLBACK ferror_file_func ( - voidpf opaque, - voidpf stream); - - -voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) - voidpf opaque; - const char* filename; - int mode; -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - - -uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - - -uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - const void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -long ZCALLBACK ftell_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - -long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) - voidpf opaque; - voidpf stream; - uLong offset; - int origin; -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - fseek((FILE *)stream, offset, fseek_origin); - return ret; -} - -int ZCALLBACK fclose_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = fclose((FILE *)stream); - return ret; -} - -int ZCALLBACK ferror_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include +#include +#include + +# ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include +# else +# include "../zlib/zlib.h" +# endif +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func ( + voidpf opaque, + const char* filename, + int mode); + +uLong ZCALLBACK fread_file_func ( + voidpf opaque, + voidpf stream, + void* buf, + uLong size); + +uLong ZCALLBACK fwrite_file_func ( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size); + +long ZCALLBACK ftell_file_func ( + voidpf opaque, + voidpf stream); + +long ZCALLBACK fseek_file_func ( + voidpf opaque, + voidpf stream, + uLong offset, + int origin); + +int ZCALLBACK fclose_file_func ( + voidpf opaque, + voidpf stream); + +int ZCALLBACK ferror_file_func ( + voidpf opaque, + voidpf stream); + + +voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/contrib/unzip/ioapi.h b/contrib/unzip/ioapi.h index b12b6c75a..06fdd15e9 100644 --- a/contrib/unzip/ioapi.h +++ b/contrib/unzip/ioapi.h @@ -1,75 +1,75 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#ifndef _ZLIBIOAPI_H -#define _ZLIBIOAPI_H - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - -#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) -#define ZCALLBACK CALLBACK -#else -#define ZCALLBACK -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode); -typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size); -typedef uLong (ZCALLBACK *write_file_func)(voidpf opaque, voidpf stream, const void* buf, uLong size); -typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream); -typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); -typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream); -typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream); - -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - - - -void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def); - -#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) -#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) -#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) -#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) -#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) - - -#ifdef __cplusplus -} -#endif - -#endif - +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode); +typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size); +typedef uLong (ZCALLBACK *write_file_func)(voidpf opaque, voidpf stream, const void* buf, uLong size); +typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream); +typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); +typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream); +typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index e83862a43..af00f7d6f 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -1,1604 +1,1604 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - Read unzip.h for more info -*/ - -/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of -compatibility with older software. The following is from the original crypt.c. Code -woven in by Terry Thorsen 1/2003. -*/ -/* - Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - - See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. - If, for some reason, all these files are missing, the Info-ZIP license - also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html -*/ -/* - crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - */ - -/* - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - */ - - -#include -#include -#include -#include "./unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - -#ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) -# define CASESENSITIVITYDEFAULT_NO -# endif -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - - - -const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info_internal_s -{ - uLong offset_curfile;/* relative offset of local header 4 bytes */ -} unz_file_info_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - - uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - uLong offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - uLong pos_local_extrafield; /* position in the local extra field in read*/ - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - uLong rest_read_compressed; /* number of byte to be decompressed */ - uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - unz_global_info gi; /* public global information */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - uLong num_file; /* number of the current file in the zipfile*/ - uLong pos_in_central_dir; /* pos of the current file in the central dir*/ - uLong current_file_ok; /* flag about the usability of the current file*/ - uLong central_pos; /* position of the beginning of the central dir*/ - - uLong size_central_dir; /* size of the central directory */ - uLong offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info cur_file_info; /* public info about the current file in zip*/ - unz_file_info_internal cur_file_info_internal; /* private info about it*/ - file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ - int encrypted; -# ifndef NOUNCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; -# endif -} unz_s; - - -#ifndef NOUNCRYPT -#include "crypt.h" -#endif - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unzlocal_getByte ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - int *pi); - -local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - int *pi; -{ - unsigned char c; - int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unzlocal_getShort ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX); - -local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unzlocal_getLong ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX); - -local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (fileName1,fileName2) - const char* fileName1; - const char* fileName2; -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) - const char* fileName1; - const char* fileName2; - int iCaseSensitivity; -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong unzlocal_SearchCentralDir ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream); - -local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer - "zlib/zlib114.zip". - If the zipfile cannot be opened (file doesn't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) - const char *path; - zlib_filefunc_def* pzlib_filefunc_def; -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - if (pzlib_filefunc_def==NULL) - fill_fopen_filefunc(&us.z_filefunc); - else - us.z_filefunc = *pzlib_filefunc_def; - - us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - if (ZSEEK(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE(s->z_filefunc, s->filestream); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) - unzFile file; - unz_global_info *pglobal_info; -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) - uLong ulDosDate; - tm_unz* ptm; -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unzlocal_GetCurrentFileInfoInternal (unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize); - -local int unzlocal_GetCurrentFileInfoInternal (file, - pfile_info, - pfile_info_internal, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - unz_file_info_internal *pfile_info_internal; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (ZSEEK(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo (file, - pfile_info, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (file) - unzFile file; -{ - int err=UNZ_OK; - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (file) - unzFile file; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) - unzFile file; - const char *szFileName; - int iCaseSensitivity; -{ - unz_s* s; - int err; - - /* We remember the 'current' position in the file so that we can jump - * back there if we fail. - */ - unz_file_info cur_file_infoSaved; - unz_file_info_internal cur_file_info_internalSaved; - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - /* Save the current state */ - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - cur_file_infoSaved = s->cur_file_info; - cur_file_info_internalSaved = s->cur_file_info_internal; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - err = unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (err == UNZ_OK) - { - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - } - - /* We failed, so restore the state of the 'current file' to where we - * were. - */ - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - s->cur_file_info = cur_file_infoSaved; - s->cur_file_info_internal = cur_file_info_internalSaved; - return err; -} - - -/* -/////////////////////////////////////////// -// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) -// I need random access -// -// Further optimization could be realized by adding an ability -// to cache the directory in memory. The goal being a single -// comprehensive file read to put the file I need in a memory. -*/ - -/* -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; // offset in file - uLong num_of_file; // # of file -} unz_file_pos; -*/ - -extern int ZEXPORT unzGetFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - file_pos->pos_in_zip_directory = s->pos_in_central_dir; - file_pos->num_of_file = s->num_file; - - return UNZ_OK; -} - -extern int ZEXPORT unzGoToFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - int err; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - /* jump to the right spot */ - s->pos_in_central_dir = file_pos->pos_in_zip_directory; - s->num_file = file_pos->num_of_file; - - /* set the current file */ - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - /* return results */ - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* -// Unzip Helper Functions - should be here? -/////////////////////////////////////////// -*/ - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, - poffset_local_extrafield, - psize_local_extrafield) - unz_s* s; - uInt* piSizeVar; - uLong *poffset_local_extrafield; - uInt *psize_local_extrafield; -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) - unzFile file; - int* method; - int* level; - int raw; - const char* password; -{ - int err=UNZ_OK; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ -# ifndef NOUNCRYPT - char source[12]; -# else - if (password != NULL) - return UNZ_PARAMERROR; -# endif - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*) - ALLOC(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - pfile_in_zip_read_info->raw=raw; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_DEFLATED) && - (!raw)) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = (voidpf)0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - s->pfile_in_zip_read = pfile_in_zip_read_info; - -# ifndef NOUNCRYPT - if (password != NULL) - { - int i; - s->pcrc_32_tab = get_crc_table(); - init_keys(password,s->keys,s->pcrc_32_tab); - if (ZSEEK(s->z_filefunc, s->filestream, - s->pfile_in_zip_read->pos_in_zipfile + - s->pfile_in_zip_read->byte_before_the_zipfile, - SEEK_SET)!=0) - return UNZ_INTERNALERROR; - if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) - return UNZ_INTERNALERROR; - - for (i = 0; i<12; i++) - zdecode(s->keys,s->pcrc_32_tab,source[i]); - - s->pfile_in_zip_read->pos_in_zipfile+=12; - s->encrypted=1; - } -# endif - - - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (file) - unzFile file; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); -} - -extern int ZEXPORT unzOpenCurrentFilePassword (file, password) - unzFile file; - const char* password; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, password); -} - -extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) - unzFile file; - int* method; - int* level; - int raw; -{ - return unzOpenCurrentFile3(file, method, level, raw, NULL); -} - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile (file, buf, len) - unzFile file; - voidp buf; - unsigned len; -{ - int err=UNZ_OK; - uInt iRead = 0; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->read_buffer == NULL) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && - (!(pfile_in_zip_read_info->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - if ((len>pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in) && - (pfile_in_zip_read_info->raw)) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - - -# ifndef NOUNCRYPT - if(s->encrypted) - { - uInt i; - for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, - pfile_in_zip_read_info->read_buffer[i]); - } -# endif - - - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) - err = Z_DATA_ERROR; - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) - unzFile file; - voidp buf; - unsigned len; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,read_now)!=read_now) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (file) - unzFile file; -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && - (!pfile_in_zip_read_info->raw)) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) - unzFile file; - char *szComment; - uLong uSizeBuf; -{ - unz_s* s; - uLong uReadThis ; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* Additions by RX '2004 */ -extern uLong ZEXPORT unzGetOffset (file) - unzFile file; -{ - unz_s* s; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return 0; - if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) - if (s->num_file==s->gi.number_entry) - return 0; - return s->pos_in_central_dir; -} - -extern int ZEXPORT unzSetOffset (file, pos) - unzFile file; - uLong pos; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - s->pos_in_central_dir = pos; - s->num_file = s->gi.number_entry; /* hack */ - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include +#include +#include +#include "./unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi); + +local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX); + +local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX); + +local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream); + +local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) + const char *path; + zlib_filefunc_def* pzlib_filefunc_def; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal (unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) + unzFile file; + int* method; + int* level; + int raw; + const char* password; +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (file, password) + unzFile file; + const char* password; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) + unzFile file; + int* method; + int* level; + int raw; +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (file) + unzFile file; +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (file, pos) + unzFile file; + uLong pos; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/contrib/unzip/unzip.h b/contrib/unzip/unzip.h index 16fd9fd70..e3b7f24ee 100644 --- a/contrib/unzip/unzip.h +++ b/contrib/unzip/unzip.h @@ -1,358 +1,358 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - - Multi volume ZipFile (span) are not supported. - Encryption compatible with pkzip 2.04g only supported - Old compressions used by old PKZip 1.x are not supported - - - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - -*/ - -/* for more info about .ZIP format, see - http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip - http://www.info-zip.org/pub/infozip/doc/ - PkWare has also a specification at : - ftp://ftp.pkware.com/probdesc.zip -*/ - -#ifndef _unz_H -#define _unz_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../zlib/zlib.h" -# endif -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen (const char *path); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ - -extern unzFile ZEXPORT unzOpen2 (const char *path, - zlib_filefunc_def* pzlib_filefunc_def); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern int ZEXPORT unzClose (unzFile file); -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo (unzFile file, - unz_global_info *pglobal_info); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment (unzFile file, - char *szComment, - uLong uSizeBuf); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile (unzFile file); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile (unzFile file); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile (unzFile file, - const char *szFileName, - int iCaseSensitivity); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -/* ****************************************** */ -/* Ryan supplied functions */ -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; /* offset in zip file directory */ - uLong num_of_file; /* # of file */ -} unz_file_pos; - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos); - -/* ****************************************** */ - -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile (unzFile file); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, - const char* password); -/* - Open for reading data the current file in the zipfile. - password is a crypting password - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, - int* method, - int* level, - int raw); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, - int* method, - int* level, - int raw, - const char* password); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - - -extern int ZEXPORT unzCloseCurrentFile (unzFile file); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - -extern int ZEXPORT unzReadCurrentFile (unzFile file, - voidp buf, - unsigned len); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell (unzFile file); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof (unzFile file); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, - voidp buf, - unsigned len); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -/***************************************************************************/ - -/* Get the current file offset */ -extern uLong ZEXPORT unzGetOffset (unzFile file); - -/* Set the current file offset */ -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _unz_H */ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +# ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include +# else +# include "../zlib/zlib.h" +# endif +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen (const char *path); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 (const char *path, + zlib_filefunc_def* pzlib_filefunc_def); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose (unzFile file); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, + unz_global_info *pglobal_info); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment (unzFile file, + char *szComment, + uLong uSizeBuf); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile (unzFile file); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile (unzFile file); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile (unzFile file, + const char *szFileName, + int iCaseSensitivity); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile (unzFile file); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, + const char* password); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, + int* method, + int* level, + int raw); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, + int* method, + int* level, + int raw, + const char* password); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile (unzFile file); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile (unzFile file, + voidp buf, + unsigned len); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell (unzFile file); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof (unzFile file); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, + voidp buf, + unsigned len); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/contrib/zlib/CMakeLists.txt b/contrib/zlib/CMakeLists.txt index 5a9546038..022d3dfba 100644 --- a/contrib/zlib/CMakeLists.txt +++ b/contrib/zlib/CMakeLists.txt @@ -1,199 +1,199 @@ -cmake_minimum_required(VERSION 2.4.4) -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) - -# CMake 3.0 changed the project command, setting policy CMP0048 reverts to the old behaviour. -# See http://www.cmake.org/cmake/help/v3.0/policy/CMP0048.html -cmake_policy(PUSH) -if(CMAKE_MAJOR_VERSION GREATER 2) - cmake_policy(SET CMP0048 OLD) -endif() -project(zlib C) -cmake_policy(POP) - -set(VERSION "1.2.8") - -option(ASM686 "Enable building i686 assembly implementation for zlib") -option(AMD64 "Enable building amd64 assembly implementation for zlib") - -#set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") -#set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") -#set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") -#set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") -#set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") - -include(CheckTypeSize) -include(CheckFunctionExists) -include(CheckIncludeFile) -include(CheckCSourceCompiles) -enable_testing() - -check_include_file(sys/types.h HAVE_SYS_TYPES_H) -check_include_file(stdint.h HAVE_STDINT_H) -check_include_file(stddef.h HAVE_STDDEF_H) - -# -# Check to see if we have large file support -# -set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) -# We add these other definitions here because CheckTypeSize.cmake -# in CMake 2.4.x does not automatically do so and we want -# compatibility with CMake 2.4.x. -if(HAVE_SYS_TYPES_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) -endif() -if(HAVE_STDINT_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) -endif() -if(HAVE_STDDEF_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) -endif() -check_type_size(off64_t OFF64_T) -if(HAVE_OFF64_T) - add_definitions(-D_LARGEFILE64_SOURCE=1) -endif() -set(CMAKE_REQUIRED_DEFINITIONS) # clear variable - -# -# Check for fseeko -# -check_function_exists(fseeko HAVE_FSEEKO) -if(NOT HAVE_FSEEKO) - add_definitions(-DNO_FSEEKO) -endif() - -# -# Check for unistd.h -# -check_include_file(unistd.h Z_HAVE_UNISTD_H) - -if(MSVC) - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -endif() - -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) - # If we're doing an out of source build and the user has a zconf.h - # in their source tree... - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) - message(STATUS "Renaming") - message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") - message(STATUS "to 'zconf.h.included' because this file is included with zlib") - message(STATUS "but CMake generates it automatically in the build directory.") - file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) - endif() -endif() - -set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein - ${ZLIB_PC} @ONLY) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) - -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) - - -#============================================================================ -# zlib -#============================================================================ - -set(ZLIB_PUBLIC_HDRS - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h - zlib.h -) -set(ZLIB_PRIVATE_HDRS - crc32.h - deflate.h - gzguts.h - inffast.h - inffixed.h - inflate.h - inftrees.h - trees.h - zutil.h -) -set(ZLIB_SRCS - adler32.c - compress.c - crc32.c - deflate.c - gzclose.c - gzlib.c - gzread.c - gzwrite.c - inflate.c - infback.c - inftrees.c - inffast.c - trees.c - uncompr.c - zutil.c -) - -if(NOT MINGW) - set(ZLIB_DLL_SRCS - win32/zlib1.rc # If present will override custom build rule below. - ) -endif() - -if(CMAKE_COMPILER_IS_GNUCC) - if(ASM686) - set(ZLIB_ASMS contrib/asm686/match.S) - elseif (AMD64) - set(ZLIB_ASMS contrib/amd64/amd64-match.S) - endif () - - if(ZLIB_ASMS) - add_definitions(-DASMV) - set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) - endif() -endif() - -if(MSVC) - if(ASM686) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx86/inffas32.asm - contrib/masmx86/match686.asm - ) - elseif (AMD64) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx64/gvmat64.asm - contrib/masmx64/inffasx64.asm - ) - endif() - - if(ZLIB_ASMS) - add_definitions(-DASMV -DASMINF) - endif() -endif() - -# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) -string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" - "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) - -if(MINGW) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) - endif() - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) - set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) -endif(MINGW) - -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -INSTALL( TARGETS zlibstatic - LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} - COMPONENT ${LIBASSIMP_COMPONENT}) +cmake_minimum_required(VERSION 2.4.4) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) + +# CMake 3.0 changed the project command, setting policy CMP0048 reverts to the old behaviour. +# See http://www.cmake.org/cmake/help/v3.0/policy/CMP0048.html +cmake_policy(PUSH) +if(CMAKE_MAJOR_VERSION GREATER 2) + cmake_policy(SET CMP0048 OLD) +endif() +project(zlib C) +cmake_policy(POP) + +set(VERSION "1.2.8") + +option(ASM686 "Enable building i686 assembly implementation for zlib") +option(AMD64 "Enable building amd64 assembly implementation for zlib") + +#set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") +#set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") +#set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") +#set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") +#set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + +include(CheckTypeSize) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +enable_testing() + +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stddef.h HAVE_STDDEF_H) + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) +# We add these other definitions here because CheckTypeSize.cmake +# in CMake 2.4.x does not automatically do so and we want +# compatibility with CMake 2.4.x. +if(HAVE_SYS_TYPES_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) +endif() +if(HAVE_STDINT_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) +endif() +if(HAVE_STDDEF_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) +endif() +check_type_size(off64_t OFF64_T) +if(HAVE_OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko +# +check_function_exists(fseeko HAVE_FSEEKO) +if(NOT HAVE_FSEEKO) + add_definitions(-DNO_FSEEKO) +endif() + +# +# Check for unistd.h +# +check_include_file(unistd.h Z_HAVE_UNISTD_H) + +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + # If we're doing an out of source build and the user has a zconf.h + # in their source tree... + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) + message(STATUS "Renaming") + message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") + message(STATUS "to 'zconf.h.included' because this file is included with zlib") + message(STATUS "but CMake generates it automatically in the build directory.") + file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) + endif() +endif() + +set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein + ${ZLIB_PC} @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) + +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + + +#============================================================================ +# zlib +#============================================================================ + +set(ZLIB_PUBLIC_HDRS + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h + zlib.h +) +set(ZLIB_PRIVATE_HDRS + crc32.h + deflate.h + gzguts.h + inffast.h + inffixed.h + inflate.h + inftrees.h + trees.h + zutil.h +) +set(ZLIB_SRCS + adler32.c + compress.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + inflate.c + infback.c + inftrees.c + inffast.c + trees.c + uncompr.c + zutil.c +) + +if(NOT MINGW) + set(ZLIB_DLL_SRCS + win32/zlib1.rc # If present will override custom build rule below. + ) +endif() + +if(CMAKE_COMPILER_IS_GNUCC) + if(ASM686) + set(ZLIB_ASMS contrib/asm686/match.S) + elseif (AMD64) + set(ZLIB_ASMS contrib/amd64/amd64-match.S) + endif () + + if(ZLIB_ASMS) + add_definitions(-DASMV) + set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) + endif() +endif() + +if(MSVC) + if(ASM686) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx86/inffas32.asm + contrib/masmx86/match686.asm + ) + elseif (AMD64) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx64/gvmat64.asm + contrib/masmx64/inffasx64.asm + ) + endif() + + if(ZLIB_ASMS) + add_definitions(-DASMV -DASMINF) + endif() +endif() + +# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) +string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" + "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) + +if(MINGW) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) + endif() + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + COMMAND ${CMAKE_RC_COMPILER} + -D GCC_WINDRES + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) +endif(MINGW) + +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +INSTALL( TARGETS zlibstatic + LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} + COMPONENT ${LIBASSIMP_COMPONENT}) diff --git a/contrib/zlib_note.txt b/contrib/zlib_note.txt index 538f8011f..cc274f0bf 100644 --- a/contrib/zlib_note.txt +++ b/contrib/zlib_note.txt @@ -1,11 +1,11 @@ -This is a heavily modified and shrinked version of zlib 1.2.3 - -- Removed comments from zlib.h -- Removed gzip/zip archive I/O -- Removed infback.c -- Added Assimp #idefs to exclude it if not needed -- Disabled debug macros in zutil.h - -Assimp itself does not use the compression part yet, so -it needn't be compiled (trees.c, deflate.c, compress.c). +This is a heavily modified and shrinked version of zlib 1.2.3 + +- Removed comments from zlib.h +- Removed gzip/zip archive I/O +- Removed infback.c +- Added Assimp #idefs to exclude it if not needed +- Disabled debug macros in zutil.h + +Assimp itself does not use the compression part yet, so +it needn't be compiled (trees.c, deflate.c, compress.c). Currently these units are just used by assimp_cmd. \ No newline at end of file diff --git a/doc/Preamble.txt b/doc/Preamble.txt index 5b2fcaa73..0722a48e1 100644 --- a/doc/Preamble.txt +++ b/doc/Preamble.txt @@ -1,40 +1,40 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, 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. ---------------------------------------------------------------------------- +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, 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. +--------------------------------------------------------------------------- */ \ No newline at end of file diff --git a/doc/dox.h b/doc/dox.h index 16a5b3806..aad0925bd 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -1,1705 +1,1705 @@ -/** @file dox.h - * @brief General documentation built from a doxygen comment - */ - -/** -@mainpage assimp - Open Asset Import Library - - - -@section intro Introduction - -assimp is a library to load and process geometric scenes from various data formats. It is tailored at typical game -scenarios by supporting a node hierarchy, static or skinned meshes, materials, bone animations and potential texture data. -The library is *not* designed for speed, it is primarily useful for importing assets from various sources once and -storing it in a engine-specific format for easy and fast every-day-loading. assimp is also able to apply various post -processing steps to the imported data such as conversion to indexed meshes, calculation of normals or tangents/bitangents -or conversion from right-handed to left-handed coordinate systems. - -assimp currently supports the following file formats (note that some loaders lack some features of their formats because -some file formats contain data not supported by assimp, some stuff would require so much conversion work -that it has not been implemented yet and some (most ...) formats lack proper specifications): -
-
-Collada ( *.dae;*.xml )
-Blender ( *.blend ) 3
-Biovision BVH ( *.bvh )
-3D Studio Max 3DS ( *.3ds )
-3D Studio Max ASE ( *.ase )
-Wavefront Object ( *.obj )
-Stanford Polygon Library ( *.ply )
-AutoCAD DXF ( *.dxf )
-IFC-STEP ( *.ifc )
-Neutral File Format ( *.nff )
-Sense8 WorldToolkit ( *.nff )
-Valve Model ( *.smd,*.vta ) 3
-Quake I ( *.mdl )
-Quake II ( *.md2 )
-Quake III ( *.md3 )
-Quake 3 BSP ( *.pk3 ) 1
-RtCW ( *.mdc )
-Doom 3 ( *.md5mesh;*.md5anim;*.md5camera )
-DirectX X ( *.x ).
-Quick3D ( *.q3o;*q3s ).
-Raw Triangles ( *.raw ).
-AC3D ( *.ac ).
-Stereolithography ( *.stl ).
-Autodesk DXF ( *.dxf ).
-Irrlicht Mesh ( *.irrmesh;*.xml ).
-Irrlicht Scene ( *.irr;*.xml ).
-Object File Format ( *.off ).
-Terragen Terrain ( *.ter )
-3D GameStudio Model ( *.mdl )
-3D GameStudio Terrain ( *.hmp )
-Ogre (*.mesh.xml, *.skeleton.xml, *.material)3
-Milkshape 3D ( *.ms3d )
-LightWave Model ( *.lwo )
-LightWave Scene ( *.lws )
-Modo Model ( *.lxo )
-CharacterStudio Motion ( *.csm )
-Stanford Ply ( *.ply )
-TrueSpace ( *.cob, *.scn )2

-
-See the @link importer_notes Importer Notes Page @endlink for informations, what a specific importer can do and what not. -Note that although this paper claims to be the official documentation, -http://assimp.sourceforge.net/main_features_formats.html -
is usually the most up-to-date list of file formats supported by the library.
- -1: Experimental loaders
-2: Indicates very limited support - many of the format's features don't map to Assimp's data structures.
-3: These formats support animations, but assimp doesn't yet support them (or they're buggy)
-
-
- -assimp is independent of the Operating System by nature, providing a C++ interface for easy integration -with game engines and a C interface to allow bindings to other programming languages. At the moment the library runs -on any little-endian platform including X86/Windows/Linux/Mac and X64/Windows/Linux/Mac. Special attention -was paid to keep the library as free as possible from dependencies. - -Big endian systems such as PPC-Macs or PPC-Linux systems are not officially supported at the moment. However, most -formats handle the required endian conversion correctly, so large parts of the library should work. - -The assimp linker library and viewer application are provided under the BSD 3-clause license. This basically means -that you are free to use it in open- or closed-source projects, for commercial or non-commercial purposes as you like -as long as you retain the license informations and take own responsibility for what you do with it. For details see -the LICENSE file. - -You can find test models for almost all formats in the /test/models directory. Beware, they're *free*, -but not all of them are *open-source*. If there's an accompagning '\source.txt' file don't forget to read it. - -@section main_install Installation - -assimp can be used in two ways: linking against the pre-built libraries or building the library on your own. The former -option is the easiest, but the assimp distribution contains pre-built libraries only for Visual C++ 2005 and 2008. For other -compilers you'll have to build assimp for yourself. Which is hopefully as hassle-free as the other way, but needs a bit -more work. Both ways are described at the @link install Installation page. @endlink - -@section main_usage Usage - -When you're done integrating the library into your IDE / project, you can now start using it. There are two separate -interfaces by which you can access the library: a C++ interface and a C interface using flat functions. While the former -is easier to handle, the latter also forms a point where other programming languages can connect to. Upto the moment, though, -there are no bindings for any other language provided. Have a look at the @link usage Usage page @endlink for a detailed explanation and code examples. - -@section main_data Data Structures - -When the importer successfully completed its job, the imported data is returned in an aiScene structure. This is the root -point from where you can access all the various data types that a scene/model file can possibly contain. The -@link data Data Structures page @endlink describes how to interpret this data. - -@section ext Extending the library - -There are many 3d file formats in the world, and we're happy to support as many as possible. If you need support for -a particular file format, why not implement it yourself and add it to the library? Writing importer plugins for -assimp is considerably easy, as the whole postprocessing infrastructure is available and does much of the work for you. -See the @link extend Extending the library @endlink page for more information. - - - -@section main_support Support & Feedback - -If you have any questions/comments/suggestions/bug reports you're welcome to post them in our -forums. Alternatively there's -a mailing list, -assimp-discussions. - - -*/ - - -/** -@page install Installation - - -@section install_prebuilt Using the pre-built libraries with Visual C++ 8/9 - -If you develop at Visual Studio 2005 or 2008, you can simply use the pre-built linker libraries provided in the distribution. -Extract all files to a place of your choice. A directory called "assimp" will be created there. Add the assimp/include path -to your include paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->Include files) -and the assimp/lib/<Compiler> path to your linker paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->Library files). -This is neccessary only once to setup all paths inside you IDE. - -To use the library in your C++ project you have to include either <assimp/Importer.hpp> or <assimp/cimport.h> plus some others starting with <types.h>. -If you set up your IDE correctly the compiler should be able to find the files. Then you have to add the linker library to your -project dependencies. Link to /lib//assimp.lib. config-name is one of the predefined -project configs. For static linking, use release/debug. See the sections below on this page for more information on the -other build configs. -If done correctly you should now be able to compile, link, -run and use the application. If the linker complains about some integral functions being defined twice you propably have -mixed the runtimes. Recheck the project configuration (project properties -> C++ -> Code generation -> Runtime) if you use -static runtimes (Multithreaded / Multithreaded Debug) or dynamic runtimes (Multithreaded DLL / Multithreaded Debug DLL). -Choose the assimp linker lib accordingly. -

-Please don't forget to also read the @ref assimp_stl section on MSVC and the STL. - -@section assimp_stl Microsoft Compilers and the C++ Standard Library - -In VC8 and VC9 Microsoft introduced some Standard Library debugging features. A good example are improved iterator checks and -various useful debug checks. The problem is the performance penalty that incurs with those extra checks. - -Most of these security enhancements are active in release builds by default, rendering assimp several times -slower. However, it is possible to disable them by setting - -@code -_HAS_ITERATOR_DEBUGGING=0 -_SECURE_SCL=0 -@endcode - -in the preprocessor options (or alternatively in the source code, just before the STL is included for the first time). -assimp's vc8 and vc9 configs enable these flags by default. - -If you're linking statically against assimp: Make sure your applications uses the same STl settings! -If you do not, there are two binary incompatible STL versions mangled together and you'll crash. -Alternatively you can disable the fast STL settings for assimp by removing the 'FastSTL' property sheet from -the vc project file. - -If you're using assimp in a DLL/SO: It's ok. There's no STL used in the binary DLL/SO interface, so it doesn't care whether -your application uses the same STL settings or not. -

-Another option is to build against a different STL implementation, for example STlport. There's a special -@ref assimp_stlport section that has a description how to achieve this. - - -@section install_own Building the library from scratch - -To build the library on your own you first have to get hold of the dependencies. Fortunately, special attention was paid to -keep the list of dependencies short. Unfortunately, the only dependency is boost which -can be a bit painful to set up for certain development environments. Boost is a widely used collection of classes and -functions for various purposes. Chances are that it was already installed along with your compiler. If not, you have to install -it for yourself. Read the "Getting Started" section of the Boost documentation for how to setup boost. VisualStudio users -can use a comfortable installer from -http://www.boost-consulting.com/products/free. Choose the appropriate version of boost for your runtime of choice. - -If you don't want to use boost, you can build against our "Boost-Workaround". It consists of very small -implementations of the various boost utility classes used. However, you'll lose functionality (e.g. threading) by doing this. -So, if you can use boost, you should use boost. Otherwise, See the @link use_noboost NoBoost-Section @endlink -later on this page for the details of the workaround. - -Once boost is working, you have to set up a project for the assimp library in your favorite IDE. If you use VC2005 or -VC2008, you can simply load the solution or project files in the workspaces/ folder, otherwise you have to create a new -package and add all the headers and source files from the include/ and code/ directories. Set the temporary output folder -to obj/, for example, and redirect the output folder to bin/. Then build the library - it should compile and link fine. - -The last step is to integrate the library into your project. This is basically the same task as described in the -"Using the pre-built libraries" section above: add the include/ and bin/ directories to your IDE's paths so that the compiler can find -the library files. Alternatively you can simply add the assimp project to your project's overall solution and build it inside -your solution. - - -@section use_noboost Building without boost. - -The Boost-Workaround consists of dummy replacements for some boost utility templates. Currently there are replacements for - - - boost.scoped_ptr - - boost.scoped_array - - boost.format - - boost.random - - boost.common_factor - - boost.foreach - - boost.tuple - - boost.make_shared - -These implementations are very limited and are not intended for use outside assimp. A compiler -with full support for partial template specializations is required. To enable the workaround, put the following in -your compiler's list of predefined macros: -@code -#define ASSIMP_BUILD_BOOST_WORKAROUND -@endcode -
-If you're working with the provided solutions for Visual Studio use the -noboost build configs.
- -assimp_BUILD_BOOST_WORKAROUND implies assimp_BUILD_SINGLETHREADED.
-See the @ref assimp_st section -for more details. - - - - -@section assimp_dll Windows DLL Build - -assimp can be built as DLL. You just need to select a -dll config from the list of project -configs and you're fine. - -NOTE: Theoretically, assimp-dll can be used with multithreaded (non-dll) runtime libraries, -as long as you don't utilize any non-public stuff from the code folder. However, if you happen -to encounter *very* strange problems, try changing the runtime to Multithreaded (Debug) DLL. - -@section assimp_stlport Building against STLport - -STLport is a free, fast and secure STL replacement that works with -all major compilers and platforms. To get it, download the latest release from -. -Usually you'll just need to run 'configure' + a makefile (see their README for more details). -Don't miss to add /stlport to your compiler's default include paths - prior -to the directory where your compiler vendor's headers lie. Do the same for /lib and -recompile assimp. To ensure you're really building against STLport see aiGetCompileFlags(). -
-In our testing, STLport builds tend to be a bit faster than builds against Microsoft's -C++ Standard Library. - -*/ - - -/** -@page usage Usage - -@section access_cpp Access by C++ class interface - -The assimp library can be accessed by both a class or flat function interface. The C++ class -interface is the preferred way of interaction: you create an instance of class Assimp::Importer, -maybe adjust some settings of it and then call Assimp::Importer::ReadFile(). The class will -read the files and process its data, handing back the imported data as a pointer to an aiScene -to you. You can now extract the data you need from the file. The importer manages all the resources -for itsself. If the importer is destroyed, all the data that was created/read by it will be -destroyed, too. So the easiest way to use the Importer is to create an instance locally, use its -results and then simply let it go out of scope. - -C++ example: -@code -#include // C++ importer interface -#include // Output data structure -#include // Post processing flags - -bool DoTheImportThing( const std::string& pFile) -{ - // Create an instance of the Importer class - Assimp::Importer importer; - - // And have it read the given file with some example postprocessing - // Usually - if speed is not the most important aspect for you - you'll - // propably to request more postprocessing than we do in this example. - const aiScene* scene = importer.ReadFile( pFile, - aiProcess_CalcTangentSpace | - aiProcess_Triangulate | - aiProcess_JoinIdenticalVertices | - aiProcess_SortByPType); - - // If the import failed, report it - if( !scene) - { - DoTheErrorLogging( importer.GetErrorString()); - return false; - } - - // Now we can access the file's contents. - DoTheSceneProcessing( scene); - - // We're done. Everything will be cleaned up by the importer destructor - return true; -} -@endcode - -What exactly is read from the files and how you interpret it is described at the @ref data page. @endlink The post processing steps that the assimp library can apply to the -imported data are listed at #aiPostProcessSteps. See the @ref pp Post proccessing page for more details. - -Note that the aiScene data structure returned is declared 'const'. Yes, you can get rid of -these 5 letters with a simple cast. Yes, you may do that. No, it's not recommended (and it's -suicide in DLL builds if you try to use new or delete on any of the arrays in the scene). - -@section access_c Access by plain-c function interface - -The plain function interface is just as simple, but requires you to manually call the clean-up -after you're done with the imported data. To start the import process, call aiImportFile() -with the filename in question and the desired postprocessing flags like above. If the call -is successful, an aiScene pointer with the imported data is handed back to you. When you're -done with the extraction of the data you're interested in, call aiReleaseImport() on the -imported scene to clean up all resources associated with the import. - -C example: -@code -#include // Plain-C interface -#include // Output data structure -#include // Post processing flags - -bool DoTheImportThing( const char* pFile) -{ - // Start the import on the given file with some example postprocessing - // Usually - if speed is not the most important aspect for you - you'll t - // probably to request more postprocessing than we do in this example. - const aiScene* scene = aiImportFile( pFile, - aiProcess_CalcTangentSpace | - aiProcess_Triangulate | - aiProcess_JoinIdenticalVertices | - aiProcess_SortByPType); - - // If the import failed, report it - if( !scene) - { - DoTheErrorLogging( aiGetErrorString()); - return false; - } - - // Now we can access the file's contents - DoTheSceneProcessing( scene); - - // We're done. Release all resources associated with this import - aiReleaseImport( scene); - return true; -} -@endcode - -@section custom_io Using custom IO logic with the C++ class interface - -The assimp library needs to access files internally. This of course applies to the file you want -to read, but also to additional files in the same folder for certain file formats. By default, -standard C/C++ IO logic is used to access these files. If your application works in a special -environment where custom logic is needed to access the specified files, you have to supply -custom implementations of IOStream and IOSystem. A shortened example might look like this: - -@code -#include -#include - -// My own implementation of IOStream -class MyIOStream : public Assimp::IOStream -{ - friend class MyIOSystem; - -protected: - // Constructor protected for private usage by MyIOSystem - MyIOStream(void); - -public: - ~MyIOStream(void); - size_t Read( void* pvBuffer, size_t pSize, size_t pCount) { ... } - size_t Write( const void* pvBuffer, size_t pSize, size_t pCount) { ... } - aiReturn Seek( size_t pOffset, aiOrigin pOrigin) { ... } - size_t Tell() const { ... } - size_t FileSize() const { ... } - void Flush () { ... } -}; - -// Fisher Price - My First Filesystem -class MyIOSystem : public Assimp::IOSystem -{ - MyIOSystem() { ... } - ~MyIOSystem() { ... } - - // Check whether a specific file exists - bool Exists( const std::string& pFile) const { - .. - } - - // Get the path delimiter character we'd like to see - char GetOsSeparator() const { - return '/'; - } - - // ... and finally a method to open a custom stream - IOStream* Open( const std::string& pFile, const std::string& pMode) { - return new MyIOStream( ... ); - } - - void Close( IOStream* pFile) { delete pFile; } -}; -@endcode - -Now that your IO system is implemented, supply an instance of it to the Importer object by calling -Assimp::Importer::SetIOHandler(). - -@code -void DoTheImportThing( const std::string& pFile) -{ - Assimp::Importer importer; - // put my custom IO handling in place - importer.SetIOHandler( new MyIOSystem()); - - // the import process will now use this implementation to access any file - importer.ReadFile( pFile, SomeFlag | SomeOtherFlag); -} -@endcode - - -@section custom_io_c Using custom IO logic with the plain-c function interface - -The C interface also provides a way to override the file system. Control is not as fine-grained as for C++ although -surely enough for almost any purpose. The process is simple: - -
    -
  • Include cfileio.h -
  • Fill an aiFileIO structure with custom file system callbacks (they're self-explanatory as they work similar to the CRT's fXXX functions) -
  • .. and pass it as parameter to #aiImportFileEx -
- -@section logging Logging - -The assimp library provides an easy mechanism to log messages. For instance if you want to check the state of your -import and you just want to see, after which preprocessing step the import-process was aborted you can take a look -into the log. -Per default the assimp-library provides a default log implementation, where you can log your user specific message -by calling it as a singleton with the requested logging-type. To see how this works take a look to this: - -@code -using namespace Assimp; - -// Create a logger instance -DefaultLogger::create("",Logger::VERBOSE); - -// Now I am ready for logging my stuff -DefaultLogger::get()->info("this is my info-call"); - -// Kill it after the work is done -DefaultLogger::kill(); -@endcode - -At first you have to create the default-logger-instance (create). Now you are ready to rock and can log a -little bit around. After that you should kill it to release the singleton instance. - -If you want to integrate the assimp-log into your own GUI it my be helpful to have a mechanism writing -the logs into your own log windows. The logger interface provides this by implementing an interface called LogStream. -You can attach and detach this log stream to the default-logger instance or any implementation derived from Logger. -Just derivate your own logger from the abstract base class LogStream and overwrite the write-method: - -@code -// Example stream -class myStream : - public LogStream -{ -public: - // Constructor - myStream() - { - // empty - } - - // Destructor - ~myStream() - { - // empty - } - - // Write womethink using your own functionality - void write(const char* message) - { - ::printf("%s\n", message); - } -}; - -// Select the kinds of messages you want to receive on this log stream -const unsigned int severity = Logger::DEBUGGING|Logger::INFO|Logger::ERR|Logger::WARN; - -// Attaching it to the default logger -Assimp::DefaultLogger::get()->attachStream( new myStream(), severity ); - -@endcode - -The severity level controls the kind of message which will be written into -the attached stream. If you just want to log errors and warnings set the warn -and error severity flag for those severities. It is also possible to remove -a self defined logstream from an error severity by detaching it with the severity -flag set: - -@code - -unsigned int severity = 0; -severity |= Logger::DEBUGGING; - -// Detach debug messages from you self defined stream -Assimp::DefaultLogger::get()->attachStream( new myStream(), severity ); - -@endcode - -If you want to implement your own logger just derive from the abstract base class -#Logger and overwrite the methods debug, info, warn and error. - -If you want to see the debug-messages in a debug-configured build, the Logger-interface -provides a logging-severity. You can set it calling the following method: - -@code - -Assimp::DefaultLogger::get()->setLogSeverity( LogSeverity log_severity ); - -@endcode - -The normal logging severity supports just the basic stuff like, info, warnings and errors. -In the verbose level very fine-grained debug messages will be logged, too. Note that this -kind kind of logging might decrease import performance. -*/ - -/** -@page data Data Structures - -The assimp library returns the imported data in a collection of structures. aiScene forms the root -of the data, from here you gain access to all the nodes, meshes, materials, animations or textures -that were read from the imported file. The aiScene is returned from a successful call to -assimp::Importer::ReadFile(), aiImportFile() or aiImportFileEx() - see the @link usage Usage page @endlink -for further information on how to use the library. - -By default, all 3D data is provided in a right-handed coordinate system such as OpenGL uses. In -this coordinate system, +X points to the right, -Z points away from the viewer into the screen and -+Y points upwards. Several modeling packages such as 3D Studio Max use this coordinate system as well (or a rotated variant of it). -By contrast, some other environments use left-handed coordinate systems, a prominent example being -DirectX. If you need the imported data to be in a left-handed coordinate system, supply the -#aiProcess_MakeLeftHanded flag to the ReadFile() function call. - -The output face winding is counter clockwise. Use #aiProcess_FlipWindingOrder to get CW data. -@code -x2 - - x1 - x0 -@endcode - -Outputted polygons can be literally everything: they're probably concave, self-intersecting or non-planar, -although our built-in triangulation (#aiProcess_Triangulate postprocessing step) doesn't handle the two latter. - -The output UV coordinate system has its origin in the lower-left corner: -@code -0y|1y ---------- 1x|1y - | | - | | - | | -0x|0y ---------- 1x|0y -@endcode -Use the #aiProcess_FlipUVs flag to get UV coordinates with the upper-left corner als origin. - -All matrices in the library are row-major. That means that the matrices are stored row by row in memory, -which is similar to the OpenGL matrix layout. A typical 4x4 matrix including a translational part looks like this: -@code -X1 Y1 Z1 T1 -X2 Y2 Z2 T2 -X3 Y3 Z3 T3 -0 0 0 1 -@endcode - -... with (X1, X2, X3) being the X base vector, (Y1, Y2, Y3) being the Y base vector, (Z1, Z2, Z3) -being the Z base vector and (T1, T2, T3) being the translation part. If you want to use these matrices -in DirectX functions, you have to transpose them. - -
- -11.24.09: We changed the orientation of our quaternions to the most common convention to avoid confusion. -However, if you're a previous user of Assimp and you update the library to revisions beyond SVNREV 502, -you have to adapt your animation loading code to match the new quaternion orientation. - -
- -@section hierarchy The Node Hierarchy - -Nodes are little named entities in the scene that have a place and orientation relative to their parents. -Starting from the scene's root node all nodes can have 0 to x child nodes, thus forming a hierarchy. -They form the base on which the scene is built on: a node can refer to 0..x meshes, can be referred to -by a bone of a mesh or can be animated by a key sequence of an animation. DirectX calls them "frames", -others call them "objects", we call them aiNode. - -A node can potentially refer to single or multiple meshes. The meshes are not stored inside the node, but -instead in an array of aiMesh inside the aiScene. A node only refers to them by their array index. This also means -that multiple nodes can refer to the same mesh, which provides a simple form of instancing. A mesh referred to -by this way lives in the node's local coordinate system. If you want the mesh's orientation in global -space, you'd have to concatenate the transformations from the referring node and all of its parents. - -Most of the file formats don't really support complex scenes, though, but a single model only. But there are -more complex formats such as .3ds, .x or .collada scenes which may contain an arbitrary complex -hierarchy of nodes and meshes. I for myself would suggest a recursive filter function such as the -following pseudocode: - -@code -void CopyNodesWithMeshes( aiNode node, SceneObject targetParent, Matrix4x4 accTransform) -{ - SceneObject parent; - Matrix4x4 transform; - - // if node has meshes, create a new scene object for it - if( node.mNumMeshes > 0) - { - SceneObjekt newObject = new SceneObject; - targetParent.addChild( newObject); - // copy the meshes - CopyMeshes( node, newObject); - - // the new object is the parent for all child nodes - parent = newObject; - transform.SetUnity(); - } else - { - // if no meshes, skip the node, but keep its transformation - parent = targetParent; - transform = node.mTransformation * accTransform; - } - - // continue for all child nodes - for( all node.mChildren) - CopyNodesWithMeshes( node.mChildren[a], parent, transform); -} -@endcode - -This function copies a node into the scene graph if it has children. If yes, a new scene object -is created for the import node and the node's meshes are copied over. If not, no object is created. -Potential child objects will be added to the old targetParent, but there transformation will be correct -in respect to the global space. This function also works great in filtering the bone nodes - nodes -that form the bone hierarchy for another mesh/node, but don't have any mesh themselves. - -@section meshes Meshes - -All meshes of an imported scene are stored in an array of aiMesh* inside the aiScene. Nodes refer -to them by their index in the array and providing the coordinate system for them, too. One mesh uses -only a single material everywhere - if parts of the model use a different material, this part is -moved to a separate mesh at the same node. The mesh refers to its material in the same way as the -node refers to its meshes: materials are stored in an array inside aiScene, the mesh stores only -an index into this array. - -An aiMesh is defined by a series of data channels. The presence of these data channels is defined -by the contents of the imported file: by default there are only those data channels present in the mesh -that were also found in the file. The only channels guarenteed to be always present are aiMesh::mVertices -and aiMesh::mFaces. You can test for the presence of other data by testing the pointers against NULL -or use the helper functions provided by aiMesh. You may also specify several post processing flags -at Importer::ReadFile() to let assimp calculate or recalculate additional data channels for you. - -At the moment, a single aiMesh may contain a set of triangles and polygons. A single vertex does always -have a position. In addition it may have one normal, one tangent and bitangent, zero to AI_MAX_NUMBER_OF_TEXTURECOORDS -(4 at the moment) texture coords and zero to AI_MAX_NUMBER_OF_COLOR_SETS (4) vertex colors. In addition -a mesh may or may not have a set of bones described by an array of aiBone structures. How to interpret -the bone information is described later on. - -@section material Materials - -See the @link materials Material System Page. @endlink - -@section bones Bones - -A mesh may have a set of bones in the form of aiBone structures.. Bones are a means to deform a mesh -according to the movement of a skeleton. Each bone has a name and a set of vertices on which it has influence. -Its offset matrix declares the transformation needed to transform from mesh space to the local space of this bone. - -Using the bones name you can find the corresponding node in the node hierarchy. This node in relation -to the other bones' nodes defines the skeleton of the mesh. Unfortunately there might also be -nodes which are not used by a bone in the mesh, but still affect the pose of the skeleton because -they have child nodes which are bones. So when creating the skeleton hierarchy for a mesh I -suggest the following method: - -a) Create a map or a similar container to store which nodes are necessary for the skeleton. -Pre-initialise it for all nodes with a "no".
-b) For each bone in the mesh:
-b1) Find the corresponding node in the scene's hierarchy by comparing their names.
-b2) Mark this node as "yes" in the necessityMap.
-b3) Mark all of its parents the same way until you 1) find the mesh's node or 2) the parent of the mesh's node.
-c) Recursively iterate over the node hierarchy
-c1) If the node is marked as necessary, copy it into the skeleton and check its children
-c2) If the node is marked as not necessary, skip it and do not iterate over its children.
- -Reasons: you need all the parent nodes to keep the transformation chain intact. For most -file formats and modelling packages the node hierarchy of the skeleton is either a child -of the mesh node or a sibling of the mesh node but this is by no means a requirement so you shouldn't rely on it. -The node closest to the root node is your skeleton root, from there you -start copying the hierarchy. You can skip every branch without a node being a bone in the mesh - -that's why the algorithm skips the whole branch if the node is marked as "not necessary". - -You should now have a mesh in your engine with a skeleton that is a subset of the imported hierarchy. - -@section anims Animations - -An imported scene may contain zero to x aiAnimation entries. An animation in this context is a set -of keyframe sequences where each sequence describes the orientation of a single node in the hierarchy -over a limited time span. Animations of this kind are usually used to animate the skeleton of -a skinned mesh, but there are other uses as well. - -An aiAnimation has a duration. The duration as well as all time stamps are given in ticks. To get -the correct timing, all time stamp thus have to be divided by aiAnimation::mTicksPerSecond. Beware, -though, that certain combinations of file format and exporter don't always store this information -in the exported file. In this case, mTicksPerSecond is set to 0 to indicate the lack of knowledge. - -The aiAnimation consists of a series of aiNodeAnim's. Each bone animation affects a single node in -the node hierarchy only, the name specifying which node is affected. For this node the structure -stores three separate key sequences: a vector key sequence for the position, a quaternion key sequence -for the rotation and another vector key sequence for the scaling. All 3d data is local to the -coordinate space of the node's parent, that means in the same space as the node's transformation matrix. -There might be cases where animation tracks refer to a non-existent node by their name, but this -should not be the case in your every-day data. - -To apply such an animation you need to identify the animation tracks that refer to actual bones -in your mesh. Then for every track:
-a) Find the keys that lay right before the current anim time.
-b) Optional: interpolate between these and the following keys.
-c) Combine the calculated position, rotation and scaling to a tranformation matrix
-d) Set the affected node's transformation to the calculated matrix.
- -If you need hints on how to convert to or from quaternions, have a look at the -Matrix&Quaternion FAQ. I suggest -using logarithmic interpolation for the scaling keys if you happen to need them - usually you don't -need them at all. - -@section textures Textures - -Normally textures used by assets are stored in separate files, however, -there are file formats embedding their textures directly into the model file. -Such textures are loaded into an aiTexture structure. -
-There are two cases: -
-1) The texture is NOT compressed. Its color data is directly stored -in the aiTexture structure as an array of aiTexture::mWidth * aiTexture::mHeight aiTexel structures. Each aiTexel represents a pixel (or "texel") of the texture -image. The color data is stored in an unsigned RGBA8888 format, which can be easily used for -both Direct3D and OpenGL (swizzling the order of the color components might be necessary). -RGBA8888 has been chosen because it is well-known, easy to use and natively -supported by nearly all graphics APIs. -
-2) This applies if aiTexture::mHeight == 0 is fullfilled. Then, texture is stored in a -"compressed" format such as DDS or PNG. The term "compressed" does not mean that the -texture data must actually be compressed, however the texture was found in the -model file as if it was stored in a separate file on the harddisk. Appropriate -decoders (such as libjpeg, libpng, D3DX, DevIL) are required to load theses textures. -aiTexture::mWidth specifies the size of the texture data in bytes, aiTexture::pcData is -a pointer to the raw image data and aiTexture::achFormatHint is either zeroed or -contains the most common file extension of the embedded texture's format. This value is only -set if assimp is able to determine the file format. -*/ - - -/** -@page materials Material System - -@section General Overview -All materials are stored in an array of aiMaterial inside the aiScene. - -Each aiMesh refers to one -material by its index in the array. Due to the vastly diverging definitions and usages of material -parameters there is no hard definition of a material structure. Instead a material is defined by -a set of properties accessible by their names. Have a look at assimp/material.h to see what types of -properties are defined. In this file there are also various functions defined to test for the -presence of certain properties in a material and retrieve their values. - -@section mat_tex Textures - -Textures are organized in stacks, each stack being evaluated independently. The final color value from a particular texture stack is used in the shading equation. For example, the computed color value of the diffuse texture stack (aiTextureType_DIFFUSE) is multipled with the amount of incoming diffuse light to obtain the final diffuse color of a pixel. - -@code - - Stack Resulting equation - ------------------------- -| Constant base color | color ------------------------- -| Blend operation 0 | + ------------------------- -| Strength factor 0 | 0.25* ------------------------- -| Texture 0 | texture_0 ------------------------- -| Blend operation 1 | * ------------------------- -| Strength factor 1 | 1.0* ------------------------- -| Texture 1 | texture_1 ------------------------- - ... ... - -@endcode - -@section keys Constants - -All material key constants start with 'AI_MATKEY' (it's an ugly macro for historical reasons, don't ask). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameData TypeDefault ValueMeaningNotes
NAMEaiStringn/aThe name of the material, if available. Ignored by aiProcess_RemoveRedundantMaterials. Materials are considered equal even if their names are different.
COLOR_DIFFUSEaiColor3Dblack (0,0,0)Diffuse color of the material. This is typically scaled by the amount of incoming diffuse light (e.g. using gouraud shading) ---
COLOR_SPECULARaiColor3Dblack (0,0,0)Specular color of the material. This is typically scaled by the amount of incoming specular light (e.g. using phong shading) ---
COLOR_AMBIENTaiColor3Dblack (0,0,0)Ambient color of the material. This is typically scaled by the amount of ambient light ---
COLOR_EMISSIVEaiColor3Dblack (0,0,0)Emissive color of the material. This is the amount of light emitted by the object. In real time applications it will usually not affect surrounding objects, but raytracing applications may wish to treat emissive objects as light sources. ---
COLOR_TRANSPARENTaiColor3Dblack (0,0,0)Defines the transparent color of the material, this is the color to be multiplied with the color of - translucent light to construct the final 'destination color' for a particular position in the screen buffer. T ---
WIREFRAMEintfalseSpecifies whether wireframe rendering must be turned on for the material. 0 for false, !0 for true. ---
TWOSIDEDintfalseSpecifies whether meshes using this material must be rendered without backface culling. 0 for false, !0 for true. Some importers set this property if they don't know whether the output face oder is right. As long as it is not set, you may safely enable backface culling.
SHADING_MODELintgouraudOne of the #aiShadingMode enumerated values. Defines the library shading model to use for (real time) rendering to approximate the original look of the material as closely as possible. The presence of this key might indicate a more complex material. If absent, assume phong shading only if a specular exponent is given.
BLEND_FUNCintfalseOne of the #aiBlendMode enumerated values. Defines how the final color value in the screen buffer is computed from the given color at that position and the newly computed color from the material. Simply said, alpha blending settings.-
OPACITYfloat1.0Defines the opacity of the material in a range between 0..1.Use this value to decide whether you have to activate alpha blending for rendering. OPACITY != 1 usually also implies TWOSIDED=1 to avoid cull artifacts.
SHININESSfloat0.fDefines the shininess of a phong-shaded material. This is actually the exponent of the phong specular equationSHININESS=0 is equivalent to SHADING_MODEL=aiShadingMode_Gouraud.
SHININESS_STRENGTHfloat1.0Scales the specular color of the material.This value is kept separate from the specular color by most modelers, and so do we.
REFRACTIfloat1.0Defines the Index Of Refraction for the material. That's not supported by most file formats.Might be of interest for raytracing.
TEXTURE(t,n)aiStringn/aDefines the path to the n'th texture on the stack 't', where 'n' is any value >= 0 and 't' is one of the #aiTextureType enumerated values.See the 'Textures' section above.
TEXBLEND(t,n)floatn/aDefines the strength the n'th texture on the stack 't'. All color components (rgb) are multipled with this factor *before* any further processing is done.-
TEXOP(t,n)intn/aOne of the #aiTextureOp enumerated values. Defines the arithmetic operation to be used to combine the n'th texture on the stack 't' with the n-1'th. TEXOP(t,0) refers to the blend operation between the base color for this stack (e.g. COLOR_DIFFUSE for the diffuse stack) and the first texture.-
MAPPING(t,n)intn/aDefines how the input mapping coordinates for sampling the n'th texture on the stack 't' are computed. Usually explicit UV coordinates are provided, but some model file formats might also be using basic shapes, such as spheres or cylinders, to project textures onto meshes.See the 'Textures' section below. #aiProcess_GenUVCoords can be used to let Assimp compute proper UV coordinates from projective mappings.
UVWSRC(t,n)intn/aDefines the UV channel to be used as input mapping coordinates for sampling the n'th texture on the stack 't'. All meshes assigned to this material share the same UV channel setupPresence of this key implies MAPPING(t,n) to be #aiTextureMapping_UV. See @ref uvwsrc for more details.
MAPPINGMODE_U(t,n)intn/aAny of the #aiTextureMapMode enumerated values. Defines the texture wrapping mode on the x axis for sampling the n'th texture on the stack 't'. 'Wrapping' occurs whenever UVs lie outside the 0..1 range. -
MAPPINGMODE_V(t,n)intn/aWrap mode on the v axis. See MAPPINGMODE_U. -
TEXMAP_AXIS(t,n)aiVector3Dn/a Defines the base axis to to compute the mapping coordinates for the n'th texture on the stack 't' from. This is not required for UV-mapped textures. For instance, if MAPPING(t,n) is #aiTextureMapping_SPHERE, U and V would map to longitude and latitude of a sphere around the given axis. The axis is given in local mesh space.-
TEXFLAGS(t,n)intn/a Defines miscellaneous flag for the n'th texture on the stack 't'. This is a bitwise combination of the #aiTextureFlags enumerated values.-
- -@section cpp C++-API - -Retrieving a property from a material is done using various utility functions. For C++ it's simply calling aiMaterial::Get() - -@code - -aiMaterial* mat = ..... - -// The generic way -if(AI_SUCCESS != mat->Get(,)) { - // handle epic failure here -} - -@endcode - -Simple, isn't it? To get the name of a material you would use - -@code - -aiString name; -mat->Get(AI_MATKEY_NAME,name); - -@endcode - -Or for the diffuse color ('color' won't be modified if the property is not set) - -@code - -aiColor3D color (0.f,0.f,0.f); -mat->Get(AI_MATKEY_COLOR_DIFFUSE,color); - -@endcode - -Note: Get() is actually a template with explicit specializations for aiColor3D, aiColor4D, aiString, float, int and some others. -Make sure that the type of the second parameter matches the expected data type of the material property (no compile-time check yet!). -Don't follow this advice if you wish to encounter very strange results. - -@section C C-API - -For good old C it's slightly different. Take a look at the aiGetMaterialGet functions. - -@code - -aiMaterial* mat = ..... - -if(AI_SUCCESS != aiGetMaterialFloat(mat,,)) { - // handle epic failure here -} - -@endcode - -To get the name of a material you would use - -@code - -aiString name; -aiGetMaterialString(mat,AI_MATKEY_NAME,&name); - -@endcode - -Or for the diffuse color ('color' won't be modified if the property is not set) - -@code - -aiColor3D color (0.f,0.f,0.f); -aiGetMaterialColor(mat,AI_MATKEY_COLOR_DIFFUSE,&color); - -@endcode - -@section uvwsrc How to map UV channels to textures (MATKEY_UVWSRC) - -The MATKEY_UVWSRC property is only present if the source format doesn't specify an explicit mapping from -textures to UV channels. Many formats don't do this and assimp is not aware of a perfect rule either. - -Your handling of UV channels needs to be flexible therefore. Our recommendation is to use logic like this -to handle most cases properly: - -@verbatim -have only one uv channel? - assign channel 0 to all textures and break - -for all textures - have uvwsrc for this texture? - assign channel specified in uvwsrc - else - assign channels in ascending order for all texture stacks, - i.e. diffuse1 gets channel 1, opacity0 gets channel 0. - -@endverbatim - -@section pseudo Pseudo Code Listing - -For completeness, the following is a very rough pseudo-code sample showing how to evaluate Assimp materials in your -shading pipeline. You'll probably want to limit your handling of all those material keys to a reasonable subset suitable for your purposes -(for example most 3d engines won't support highly complex multi-layer materials, but many 3d modellers do). - -Also note that this sample is targeted at a (shader-based) rendering pipeline for real time graphics. - -@code - -// --------------------------------------------------------------------------------------- -// Evaluate multiple textures stacked on top of each other -float3 EvaluateStack(stack) -{ - // For the 'diffuse' stack stack.base_color would be COLOR_DIFFUSE - // and TEXTURE(aiTextureType_DIFFUSE,n) the n'th texture. - - float3 base = stack.base_color; - for (every texture in stack) - { - // assuming we have explicit & pretransformed UVs for this texture - float3 color = SampleTexture(texture,uv); - - // scale by texture blend factor - color *= texture.blend; - - if (texture.op == add) - base += color; - else if (texture.op == multiply) - base *= color; - else // other blend ops go here - } - return base; -} - -// --------------------------------------------------------------------------------------- -// Compute the diffuse contribution for a pixel -float3 ComputeDiffuseContribution() -{ - if (shading == none) - return float3(1,1,1); - - float3 intensity (0,0,0); - for (all lights in range) - { - float fac = 1.f; - if (shading == gouraud) - fac = lambert-term .. - else // other shading modes go here - - // handling of different types of lights, such as point or spot lights - // ... - - // and finally sum the contribution of this single light ... - intensity += light.diffuse_color * fac; - } - // ... and combine the final incoming light with the diffuse color - return EvaluateStack(diffuse) * intensity; -} - -// --------------------------------------------------------------------------------------- -// Compute the specular contribution for a pixel -float3 ComputeSpecularContribution() -{ - if (shading == gouraud || specular_strength == 0 || specular_exponent == 0) - return float3(0,0,0); - - float3 intensity (0,0,0); - for (all lights in range) - { - float fac = 1.f; - if (shading == phong) - fac = phong-term .. - else // other specular shading modes go here - - // handling of different types of lights, such as point or spot lights - // ... - - // and finally sum the specular contribution of this single light ... - intensity += light.specular_color * fac; - } - // ... and combine the final specular light with the specular color - return EvaluateStack(specular) * intensity * specular_strength; -} - -// --------------------------------------------------------------------------------------- -// Compute the ambient contribution for a pixel -float3 ComputeAmbientContribution() -{ - if (shading == none) - return float3(0,0,0); - - float3 intensity (0,0,0); - for (all lights in range) - { - float fac = 1.f; - - // handling of different types of lights, such as point or spot lights - // ... - - // and finally sum the ambient contribution of this single light ... - intensity += light.ambient_color * fac; - } - // ... and combine the final ambient light with the ambient color - return EvaluateStack(ambient) * intensity; -} - -// --------------------------------------------------------------------------------------- -// Compute the final color value for a pixel -// @param prev Previous color at that position in the framebuffer -float4 PimpMyPixel (float4 prev) -{ - // .. handle displacement mapping per vertex - // .. handle bump/normal mapping - - // Get all single light contribution terms - float3 diff = ComputeDiffuseContribution(); - float3 spec = ComputeSpecularContribution(); - float3 ambi = ComputeAmbientContribution(); - - // .. and compute the final color value for this pixel - float3 color = diff + spec + ambi; - float3 opac = EvaluateStack(opacity); - - // note the *slightly* strange meaning of additive and multiplicative blending here ... - // those names will most likely be changed in future versions - if (blend_func == add) - return prev+color*opac; - else if (blend_func == multiply) - return prev*(1.0-opac)+prev*opac; - - return color; -} - -@endcode - -*/ - - - - -/** -@page perf Performance - -@section perf_overview Overview - -This page discusses general performance issues related to assimp. - -@section perf_profile Profiling - -assimp has built-in support for very basic profiling and time measurement. To turn it on, set the GLOB_MEASURE_TIME -configuration switch to true (nonzero). Results are dumped to the log file, so you need to setup -an appropriate logger implementation with at least one output stream first (see the @link logging Logging Page @endlink -for the details.). - -Note that these measurements are based on a single run of the importer and each of the post processing steps, so -a single result set is far away from being significant in a statistic sense. While precision can be improved -by running the test multiple times, the low accuracy of the timings may render the results useless -for smaller files. - -A sample report looks like this (some unrelated log messages omitted, entries grouped for clarity): - -@verbatim -Debug, T5488: START `total` -Info, T5488: Found a matching importer for this file format - - -Debug, T5488: START `import` -Info, T5488: BlendModifier: Applied the `Subdivision` modifier to `OBMonkey` -Debug, T5488: END `import`, dt= 3.516 s - - -Debug, T5488: START `preprocess` -Debug, T5488: END `preprocess`, dt= 0.001 s -Info, T5488: Entering post processing pipeline - - -Debug, T5488: START `postprocess` -Debug, T5488: RemoveRedundantMatsProcess begin -Debug, T5488: RemoveRedundantMatsProcess finished -Debug, T5488: END `postprocess`, dt= 0.001 s - - -Debug, T5488: START `postprocess` -Debug, T5488: TriangulateProcess begin -Info, T5488: TriangulateProcess finished. All polygons have been triangulated. -Debug, T5488: END `postprocess`, dt= 3.415 s - - -Debug, T5488: START `postprocess` -Debug, T5488: SortByPTypeProcess begin -Info, T5488: Points: 0, Lines: 0, Triangles: 1, Polygons: 0 (Meshes, X = removed) -Debug, T5488: SortByPTypeProcess finished - -Debug, T5488: START `postprocess` -Debug, T5488: JoinVerticesProcess begin -Debug, T5488: Mesh 0 (unnamed) | Verts in: 503808 out: 126345 | ~74.922 -Info, T5488: JoinVerticesProcess finished | Verts in: 503808 out: 126345 | ~74.9 -Debug, T5488: END `postprocess`, dt= 2.052 s - -Debug, T5488: START `postprocess` -Debug, T5488: FlipWindingOrderProcess begin -Debug, T5488: FlipWindingOrderProcess finished -Debug, T5488: END `postprocess`, dt= 0.006 s - - -Debug, T5488: START `postprocess` -Debug, T5488: LimitBoneWeightsProcess begin -Debug, T5488: LimitBoneWeightsProcess end -Debug, T5488: END `postprocess`, dt= 0.001 s - - -Debug, T5488: START `postprocess` -Debug, T5488: ImproveCacheLocalityProcess begin -Debug, T5488: Mesh 0 | ACMR in: 0.851622 out: 0.718139 | ~15.7 -Info, T5488: Cache relevant are 1 meshes (251904 faces). Average output ACMR is 0.718139 -Debug, T5488: ImproveCacheLocalityProcess finished. -Debug, T5488: END `postprocess`, dt= 1.903 s - - -Info, T5488: Leaving post processing pipeline -Debug, T5488: END `total`, dt= 11.269 s -@endverbatim - -In this particular example only one fourth of the total import time was spent on the actual importing, while the rest of the -time got consumed by the #aiProcess_Triangulate, #aiProcess_JoinIdenticalVertices and #aiProcess_ImproveCacheLocality -postprocessing steps. A wise selection of postprocessing steps is therefore essential to getting good performance. -Of course this depends on the individual requirements of your application, in many of the typical use cases of assimp performance won't -matter (i.e. in an offline content pipeline). -*/ - -/** -@page threading Threading - -@section overview Overview - -This page discusses both assimps scalability in threaded environments and the precautions to be taken in order to -use it from multiple threads concurrently. - -@section threadsafety Thread-safety / using Assimp concurrently from several threads - -The library can be accessed by multiple threads simultaneously, as long as the -following prerequisites are fulfilled: - - - Users of the C++-API should ensure that they use a dedicated #Assimp::Importer instance for each thread. Constructing instances of #Assimp::Importer is expensive, so it might be a good idea to - let every thread maintain its own thread-local instance (which can be used to - load as many files as necessary). - - The C-API is thread safe. - - When supplying custom IO logic, one must make sure the underlying implementation is thread-safe. - - Custom log streams or logger replacements have to be thread-safe, too. - - - - -Multiple concurrent imports may or may not be beneficial, however. For certain file formats in conjunction with -little or no post processing IO times tend to be the performance bottleneck. Intense post processing together -with 'slow' file formats like X or Collada might scale well with multiple concurrent imports. - - -@section automt Internal threading - -Internal multi-threading is not currently implemented. -*/ - -/** -@page res Resources - -This page lists some useful resources for assimp. Note that, even though the core team has an eye on them, -we cannot guarantee the accuracy of third-party information. If in doubt, it's best to ask either on the -mailing list or on our forums on SF.net. - - - assimp comes with some sample applications, these can be found in the ./samples folder. Don't forget to read the README file. - - http://www.drivenbynostalgia.com/files/AssimpOpenGLDemo.rar - OpenGl animation sample using the library's animation import facilities. - - http://nolimitsdesigns.com/game-design/open-asset-import-library-animation-loader/ is another utility to - simplify animation playback. - - http://ogldev.atspace.co.uk/www/tutorial22/tutorial22.html - Tutorial "Loading models using the Open Asset Import Library", out of a series of OpenGl tutorials. - -*/ - - -/** -@page importer_notes Importer Notes - -
-@section blender Blender - -This section contains implementation notes for the Blender3D importer. -@subsection bl_overview Overview - -assimp provides a self-contained reimplementation of Blender's so called SDNA system (http://www.blender.org/development/architecture/notes-on-sdna/). -SDNA allows Blender to be fully backward and forward compatible and to exchange -files across all platforms. The BLEND format is thus a non-trivial binary monster and the loader tries to read the most of it, -naturally limited by the scope of the #aiScene output data structure. -Consequently, if Blender is the only modeling tool in your asset work flow, consider writing a -custom exporter from Blender if assimps format coverage does not meet the requirements. - -@subsection bl_status Current status - -The Blender loader does not support animations yet, but is apart from that considered relatively stable. - -@subsection bl_notes Notes - -When filing bugs on the Blender loader, always give the Blender version (or, even better, post the file caused the error). - -
-@section ifc IFC - -This section contains implementation notes on the IFC-STEP importer. -@subsection ifc_overview Overview - -The library provides a partial implementation of the IFC2x3 industry standard for automatized exchange of CAE/architectural -data sets. See http://en.wikipedia.org/wiki/Industry_Foundation_Classes for more information on the format. We aim -at getting as much 3D data out of the files as possible. - -@subsection ifc_status Current status - -IFC support is new and considered experimental. Please report any bugs you may encounter. - -@subsection ifc_notes Notes - -- Only the STEP-based encoding is supported. IFCZIP and IFCXML are not (but IFCZIP can simply be unzipped to get a STEP file). -- The importer leaves vertex coordinates untouched, but applies a global scaling to the root transform to - convert from whichever unit the IFC file uses to metres. -- If multiple geometric representations are provided, the choice which one to load is based on how expensive a representation seems - to be in terms of import time. The loader also avoids representation types for which it has known deficits. -- Not supported are arbitrary binary operations (binary clipping is implemented, though). -- Of the various relationship types that IFC knows, only aggregation, containment and material assignment are resolved and mapped to - the output graph. -- The implementation knows only about IFC2X3 and applies this rule set to all models it encounters, - regardless of their actual version. Loading of older or newer files may fail with parsing errors. - -@subsection ifc_metadata Metadata - -IFC file properties (IfcPropertySet) are kept as per-node metadata, see aiNode::mMetaData. - -
-@section ogre Ogre -*ATTENTION*: The Ogre-Loader is currently under development, many things have changed after this documentation was written, but they are not final enough to rewrite the documentation. So things may have changed by now! - -This section contains implementations notes for the OgreXML importer. -@subsection overview Overview -Ogre importer is currently optimized for the Blender Ogre exporter, because thats the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922 - -@subsection what What will be loaded? - -Mesh: Faces, Positions, Normals and all TexCoords. The Materialname will be used to load the material. - -Material: The right material in the file will be searched, the importer should work with materials who -have 1 technique and 1 pass in this technique. From there, the texturename (for 1 color- and 1 normalmap) and the -materialcolors (but not in custom materials) will be loaded. Also, the materialname will be set. - -Skeleton: Skeleton with Bone hierarchy (Position and Rotation, but no Scaling in the skeleton is supported), names and transformations, -animations with rotation, translation and scaling keys. - -@subsection export_Blender How to export Files from Blender -You can find informations about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp -importer will load everything correctly: -- Use either "Rendering Material" or "Custom Material" see @ref material -- do not use "Flip Up Axies to Y" -- use "Skeleton name follow mesh" - - -@subsection xml XML Format -There is a binary and a XML mesh Format from Ogre. This loader can only -Handle xml files, but don't panic, there is a command line converter, which you can use -to create XML files from Binary Files. Just look on the Ogre page for it. - -Currently you can only load meshes. So you will need to import the *.mesh.xml file, the loader will -try to find the appendant material and skeleton file. - -The skeleton file must have the same name as the mesh file, e.g. fish.mesh.xml and fish.skeleton.xml. - -@subsection material Materials -The material file can have the same name as the mesh file (if the file is model.mesh or model.mesh.xml the -loader will try to load model.material), -or you can use Importer::Importer::SetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "materiafile.material") -to specify the name of the material file. This is especially usefull if multiply materials a stored in a single file. -The importer will first try to load the material with the same name as the mesh and only if this can't be open try -to load the alternate material file. The default material filename is "Scene.material". - -We suggest that you use custom materials, because they support multiple textures (like colormap and normalmap). First of all you -should read the custom material sektion in the Ogre Blender exporter Help File, and than use the assimp.tlp template, which you -can find in scripts/OgreImpoter/Assimp.tlp in the assimp source. If you don't set all values, don't worry, they will be ignored during import. - -If you want more properties in custom materials, you can easily expand the ogre material loader, it will be just a few lines for each property. -Just look in OgreImporterMaterial.cpp - -@subsection Importer Properties -- IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME: Normally, a texture is loaded as a colormap, if no - target is specified in the - materialfile. Is this switch is enabled, texture names ending with _n, _l, _s - are used as normalmaps, lightmaps or specularmaps. -
- Property type: Bool. Default value: false. -- IMPORT_OGRE_MATERIAL_FILE: Ogre Meshes contain only the MaterialName, not the MaterialFile. - If there - is no material file with the same name as the material, Ogre Importer will - try to load this file and search the material in it. -
- Property type: String. Default value: guessed. - -@subsection todo Todo -- Load colors in custom materials -- extend custom and normal material loading -- fix bone hierarchy bug -- test everything elaboratly -- check for non existent animation keys (what happens if a one time not all bones have a key?) -*/ - - -/** -@page extend Extending the Library - -@section General - -Or - how to write your own loaders. It's easy. You just need to implement the #Assimp::BaseImporter class, -which defines a few abstract methods, register your loader, test it carefully and provide test models for it. - -OK, that sounds too easy :-). The whole procedure for a new loader merely looks like this: - -
    -
  • Create a header (FormatNameImporter.h) and a unit (FormatNameImporter.cpp) in the <root>/code/ directory
  • -
  • Add them to the following workspaces: vc8 and vc9 (the files are in the workspaces directory), CMAKE (code/CMakeLists.txt, create a new -source group for your importer and put them also to ADD_LIBRARY( assimp SHARED))
  • -
  • Include AssimpPCH.h - this is the PCH file, and it includes already most Assimp-internal stuff.
  • -
  • Open Importer.cpp and include your header just below the (include_new_importers_here) line, -guarded by a #define -@code -#if (!defined assimp_BUILD_NO_FormatName_IMPORTER) - ... -#endif -@endcode -Wrap the same guard around your .cpp!
  • - -
  • Now advance to the (register_new_importers_here) line in the Importer.cpp and register your importer there - just like all the others do.
  • -
  • Setup a suitable test environment (i.e. use AssimpView or your own application), make sure to enable -the #aiProcess_ValidateDataStructure flag and enable verbose logging. That is, simply call before you import anything: -@code -DefaultLogger::create("AssimpLog.txt",Logger::VERBOSE) -@endcode -
  • -
  • -Implement the Assimp::BaseImporter::CanRead(), Assimp::BaseImporter::InternReadFile() and Assimp::BaseImporter::GetExtensionList(). -Just copy'n'paste the template from Appendix A and adapt it for your needs. -
  • -
  • For error handling, throw a dynamic allocated ImportErrorException (see Appendix A) for critical errors, and log errors, warnings, infos and debuginfos -with DefaultLogger::get()->[error, warn, debug, info]. -
  • -
  • -Make sure that your loader compiles against all build configurations on all supported platforms. This includes -noboost! To avoid problems, -see the boost section on this page for a list of all 'allowed' boost classes (again, this grew historically when we had to accept that boost -is not THAT widely spread that one could rely on it being available everywhere). -
  • -
  • -Provide some _free_ test models in <root>/test/models/<FormatName>/ and credit their authors. -Test files for a file format shouldn't be too large (~500 KiB in total), and not too repetive. Try to cover all format features with test data. -
  • -
  • -Done! Please, share your loader that everyone can profit from it! -
  • -
- -@section properties Properties - -You can use properties to chance the behavior of you importer. In order to do so, you have to overide BaseImporter::SetupProperties, and specify -you custom properties in config.h. Just have a look to the other AI_CONFIG_IMPORT_* defines and you will understand, how it works. - -The properties can be set with Importer::SetProperty***() and can be accessed in your SetupProperties function with Importer::GetProperty***(). You can -store the properties as a member variable of your importer, they are thread safe. - -@section tnote Notes for text importers - -
    -
  • Try to make your parser as flexible as possible. Don't rely on particular layout, whitespace/tab style, -except if the file format has a strict definition, in which case you should always warn about spec violations. -But the general rule of thumb is be strict in what you write and tolerant in what you accept.
  • -
  • Call Assimp::BaseImporter::ConvertToUTF8() before you parse anything to convert foreign encodings to UTF-8. - That's not necessary for XML importers, which must use the provided IrrXML for reading.
  • -
- -@section bnote Notes for binary importers - -
    -
  • -Take care of endianess issues! Assimp importers mostly support big-endian platforms, which define the AI_BUILD_BIG_ENDIAN constant. -See the next section for a list of utilities to simplify this task. -
  • -
  • -Don't trust the input data! Check all offsets! -
  • -
- -@section util Utilities - -Mixed stuff for internal use by loaders, mostly documented (most of them are already included by AssimpPCH.h): -
    -
  • ByteSwapper (ByteSwapper.h) - manual byte swapping stuff for binary loaders.
  • -
  • StreamReader (StreamReader.h) - safe, endianess-correct, binary reading.
  • -
  • IrrXML (irrXMLWrapper.h) - for XML-parsing (SAX.
  • -
  • CommentRemover (RemoveComments.h) - remove single-line and multi-line comments from a text file.
  • -
  • fast_atof, strtoul10, strtoul16, SkipSpaceAndLineEnd, SkipToNextToken .. large family of low-level -parsing functions, mostly declared in fast_atof.h, StringComparison.h and ParsingUtils.h (a collection that grew -historically, so don't expect perfect organization).
  • -
  • ComputeNormalsWithSmoothingsGroups() (SmoothingGroups.h) - Computes normal vectors from plain old smoothing groups.
  • -
  • SkeletonMeshBuilder (SkeletonMeshBuilder.h) - generate a dummy mesh from a given (animation) skeleton.
  • -
  • StandardShapes (StandardShapes.h) - generate meshes for standard solids, such as platonic primitives, cylinders or spheres.
  • -
  • BatchLoader (BaseImporter.h) - manage imports from external files. Useful for file formats -which spread their data across multiple files.
  • -
  • SceneCombiner (SceneCombiner.h) - exhaustive toolset to merge multiple scenes. Useful for file formats -which spread their data across multiple files.
  • -
- -@section mat Filling materials - -The required definitions zo set/remove/query keys in #aiMaterial structures are declared in MaterialSystem.h, in a -#aiMaterial derivate called #aiMaterial. The header is included by AssimpPCH.h, so you don't need to bother. - -@code -aiMaterial* mat = new aiMaterial(); - -const float spec = 16.f; -mat->AddProperty(&spec, 1, AI_MATKEY_SHININESS); - -//set the name of the material: -NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);//MaterialName is a std::string - -//set the first diffuse texture -NewMaterial->AddProperty(&aiString(Texturename.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));//again, Texturename is a std::string -@endcode - -@section boost Boost - -The boost whitelist: -
    -
  • boost.scoped_ptr
  • -
  • boost.scoped_array
  • -
  • boost.format
  • -
  • boost.random
  • -
  • boost.common_factor
  • -
  • boost.foreach
  • -
  • boost.tuple
  • -
- -(if you happen to need something else, i.e. boost::thread, make this an optional feature. -assimp_BUILD_BOOST_WORKAROUND is defined for -noboost builds) - -@section appa Appendix A - Template for BaseImporter's abstract methods - -@code -// ------------------------------------------------------------------------------- -// Returns whether the class can handle the format of the given file. -bool xxxxImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - if(extension == "xxxx") { - return true; - } - if (!extension.length() || checkSig) { - // no extension given, or we're called a second time because no - // suitable loader was found yet. This means, we're trying to open - // the file and look for and hints to identify the file format. - // #Assimp::BaseImporter provides some utilities: - // - // #Assimp::BaseImporter::SearchFileHeaderForToken - for text files. - // It reads the first lines of the file and does a substring check - // against a given list of 'magic' strings. - // - // #Assimp::BaseImporter::CheckMagicToken - for binary files. It goes - // to a particular offset in the file and and compares the next words - // against a given list of 'magic' tokens. - - // These checks MUST be done (even if !checkSig) if the file extension - // is not exclusive to your format. For example, .xml is very common - // and (co)used by many formats. - } - return false; -} - -// ------------------------------------------------------------------------------- -// Get list of file extensions handled by this loader -void xxxxImporter::GetExtensionList(std::set& extensions) -{ - extensions.insert("xxx"); -} - -// ------------------------------------------------------------------------------- -void xxxxImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open xxxx file " + pFile + "."); - } - - // Your task: fill pScene - // Throw a ImportErrorException with a meaningful (!) error message if - // something goes wrong. -} - -@endcode - */ - - - /** - @page AnimationOverview Animation Overview - \section Transformations - This diagram shows how you can calculate your transformationmatrices for an animated character: - - - **/ +/** @file dox.h + * @brief General documentation built from a doxygen comment + */ + +/** +@mainpage assimp - Open Asset Import Library + + + +@section intro Introduction + +assimp is a library to load and process geometric scenes from various data formats. It is tailored at typical game +scenarios by supporting a node hierarchy, static or skinned meshes, materials, bone animations and potential texture data. +The library is *not* designed for speed, it is primarily useful for importing assets from various sources once and +storing it in a engine-specific format for easy and fast every-day-loading. assimp is also able to apply various post +processing steps to the imported data such as conversion to indexed meshes, calculation of normals or tangents/bitangents +or conversion from right-handed to left-handed coordinate systems. + +assimp currently supports the following file formats (note that some loaders lack some features of their formats because +some file formats contain data not supported by assimp, some stuff would require so much conversion work +that it has not been implemented yet and some (most ...) formats lack proper specifications): +
+
+Collada ( *.dae;*.xml )
+Blender ( *.blend ) 3
+Biovision BVH ( *.bvh )
+3D Studio Max 3DS ( *.3ds )
+3D Studio Max ASE ( *.ase )
+Wavefront Object ( *.obj )
+Stanford Polygon Library ( *.ply )
+AutoCAD DXF ( *.dxf )
+IFC-STEP ( *.ifc )
+Neutral File Format ( *.nff )
+Sense8 WorldToolkit ( *.nff )
+Valve Model ( *.smd,*.vta ) 3
+Quake I ( *.mdl )
+Quake II ( *.md2 )
+Quake III ( *.md3 )
+Quake 3 BSP ( *.pk3 ) 1
+RtCW ( *.mdc )
+Doom 3 ( *.md5mesh;*.md5anim;*.md5camera )
+DirectX X ( *.x ).
+Quick3D ( *.q3o;*q3s ).
+Raw Triangles ( *.raw ).
+AC3D ( *.ac ).
+Stereolithography ( *.stl ).
+Autodesk DXF ( *.dxf ).
+Irrlicht Mesh ( *.irrmesh;*.xml ).
+Irrlicht Scene ( *.irr;*.xml ).
+Object File Format ( *.off ).
+Terragen Terrain ( *.ter )
+3D GameStudio Model ( *.mdl )
+3D GameStudio Terrain ( *.hmp )
+Ogre (*.mesh.xml, *.skeleton.xml, *.material)3
+Milkshape 3D ( *.ms3d )
+LightWave Model ( *.lwo )
+LightWave Scene ( *.lws )
+Modo Model ( *.lxo )
+CharacterStudio Motion ( *.csm )
+Stanford Ply ( *.ply )
+TrueSpace ( *.cob, *.scn )2

+
+See the @link importer_notes Importer Notes Page @endlink for informations, what a specific importer can do and what not. +Note that although this paper claims to be the official documentation, +http://assimp.sourceforge.net/main_features_formats.html +
is usually the most up-to-date list of file formats supported by the library.
+ +1: Experimental loaders
+2: Indicates very limited support - many of the format's features don't map to Assimp's data structures.
+3: These formats support animations, but assimp doesn't yet support them (or they're buggy)
+
+
+ +assimp is independent of the Operating System by nature, providing a C++ interface for easy integration +with game engines and a C interface to allow bindings to other programming languages. At the moment the library runs +on any little-endian platform including X86/Windows/Linux/Mac and X64/Windows/Linux/Mac. Special attention +was paid to keep the library as free as possible from dependencies. + +Big endian systems such as PPC-Macs or PPC-Linux systems are not officially supported at the moment. However, most +formats handle the required endian conversion correctly, so large parts of the library should work. + +The assimp linker library and viewer application are provided under the BSD 3-clause license. This basically means +that you are free to use it in open- or closed-source projects, for commercial or non-commercial purposes as you like +as long as you retain the license informations and take own responsibility for what you do with it. For details see +the LICENSE file. + +You can find test models for almost all formats in the /test/models directory. Beware, they're *free*, +but not all of them are *open-source*. If there's an accompagning '\source.txt' file don't forget to read it. + +@section main_install Installation + +assimp can be used in two ways: linking against the pre-built libraries or building the library on your own. The former +option is the easiest, but the assimp distribution contains pre-built libraries only for Visual C++ 2005 and 2008. For other +compilers you'll have to build assimp for yourself. Which is hopefully as hassle-free as the other way, but needs a bit +more work. Both ways are described at the @link install Installation page. @endlink + +@section main_usage Usage + +When you're done integrating the library into your IDE / project, you can now start using it. There are two separate +interfaces by which you can access the library: a C++ interface and a C interface using flat functions. While the former +is easier to handle, the latter also forms a point where other programming languages can connect to. Upto the moment, though, +there are no bindings for any other language provided. Have a look at the @link usage Usage page @endlink for a detailed explanation and code examples. + +@section main_data Data Structures + +When the importer successfully completed its job, the imported data is returned in an aiScene structure. This is the root +point from where you can access all the various data types that a scene/model file can possibly contain. The +@link data Data Structures page @endlink describes how to interpret this data. + +@section ext Extending the library + +There are many 3d file formats in the world, and we're happy to support as many as possible. If you need support for +a particular file format, why not implement it yourself and add it to the library? Writing importer plugins for +assimp is considerably easy, as the whole postprocessing infrastructure is available and does much of the work for you. +See the @link extend Extending the library @endlink page for more information. + + + +@section main_support Support & Feedback + +If you have any questions/comments/suggestions/bug reports you're welcome to post them in our +forums. Alternatively there's +a mailing list, +assimp-discussions. + + +*/ + + +/** +@page install Installation + + +@section install_prebuilt Using the pre-built libraries with Visual C++ 8/9 + +If you develop at Visual Studio 2005 or 2008, you can simply use the pre-built linker libraries provided in the distribution. +Extract all files to a place of your choice. A directory called "assimp" will be created there. Add the assimp/include path +to your include paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->Include files) +and the assimp/lib/<Compiler> path to your linker paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->Library files). +This is neccessary only once to setup all paths inside you IDE. + +To use the library in your C++ project you have to include either <assimp/Importer.hpp> or <assimp/cimport.h> plus some others starting with <types.h>. +If you set up your IDE correctly the compiler should be able to find the files. Then you have to add the linker library to your +project dependencies. Link to /lib//assimp.lib. config-name is one of the predefined +project configs. For static linking, use release/debug. See the sections below on this page for more information on the +other build configs. +If done correctly you should now be able to compile, link, +run and use the application. If the linker complains about some integral functions being defined twice you propably have +mixed the runtimes. Recheck the project configuration (project properties -> C++ -> Code generation -> Runtime) if you use +static runtimes (Multithreaded / Multithreaded Debug) or dynamic runtimes (Multithreaded DLL / Multithreaded Debug DLL). +Choose the assimp linker lib accordingly. +

+Please don't forget to also read the @ref assimp_stl section on MSVC and the STL. + +@section assimp_stl Microsoft Compilers and the C++ Standard Library + +In VC8 and VC9 Microsoft introduced some Standard Library debugging features. A good example are improved iterator checks and +various useful debug checks. The problem is the performance penalty that incurs with those extra checks. + +Most of these security enhancements are active in release builds by default, rendering assimp several times +slower. However, it is possible to disable them by setting + +@code +_HAS_ITERATOR_DEBUGGING=0 +_SECURE_SCL=0 +@endcode + +in the preprocessor options (or alternatively in the source code, just before the STL is included for the first time). +assimp's vc8 and vc9 configs enable these flags by default. + +If you're linking statically against assimp: Make sure your applications uses the same STl settings! +If you do not, there are two binary incompatible STL versions mangled together and you'll crash. +Alternatively you can disable the fast STL settings for assimp by removing the 'FastSTL' property sheet from +the vc project file. + +If you're using assimp in a DLL/SO: It's ok. There's no STL used in the binary DLL/SO interface, so it doesn't care whether +your application uses the same STL settings or not. +

+Another option is to build against a different STL implementation, for example STlport. There's a special +@ref assimp_stlport section that has a description how to achieve this. + + +@section install_own Building the library from scratch + +To build the library on your own you first have to get hold of the dependencies. Fortunately, special attention was paid to +keep the list of dependencies short. Unfortunately, the only dependency is boost which +can be a bit painful to set up for certain development environments. Boost is a widely used collection of classes and +functions for various purposes. Chances are that it was already installed along with your compiler. If not, you have to install +it for yourself. Read the "Getting Started" section of the Boost documentation for how to setup boost. VisualStudio users +can use a comfortable installer from +http://www.boost-consulting.com/products/free. Choose the appropriate version of boost for your runtime of choice. + +If you don't want to use boost, you can build against our "Boost-Workaround". It consists of very small +implementations of the various boost utility classes used. However, you'll lose functionality (e.g. threading) by doing this. +So, if you can use boost, you should use boost. Otherwise, See the @link use_noboost NoBoost-Section @endlink +later on this page for the details of the workaround. + +Once boost is working, you have to set up a project for the assimp library in your favorite IDE. If you use VC2005 or +VC2008, you can simply load the solution or project files in the workspaces/ folder, otherwise you have to create a new +package and add all the headers and source files from the include/ and code/ directories. Set the temporary output folder +to obj/, for example, and redirect the output folder to bin/. Then build the library - it should compile and link fine. + +The last step is to integrate the library into your project. This is basically the same task as described in the +"Using the pre-built libraries" section above: add the include/ and bin/ directories to your IDE's paths so that the compiler can find +the library files. Alternatively you can simply add the assimp project to your project's overall solution and build it inside +your solution. + + +@section use_noboost Building without boost. + +The Boost-Workaround consists of dummy replacements for some boost utility templates. Currently there are replacements for + + - boost.scoped_ptr + - boost.scoped_array + - boost.format + - boost.random + - boost.common_factor + - boost.foreach + - boost.tuple + - boost.make_shared + +These implementations are very limited and are not intended for use outside assimp. A compiler +with full support for partial template specializations is required. To enable the workaround, put the following in +your compiler's list of predefined macros: +@code +#define ASSIMP_BUILD_BOOST_WORKAROUND +@endcode +
+If you're working with the provided solutions for Visual Studio use the -noboost build configs.
+ +assimp_BUILD_BOOST_WORKAROUND implies assimp_BUILD_SINGLETHREADED.
+See the @ref assimp_st section +for more details. + + + + +@section assimp_dll Windows DLL Build + +assimp can be built as DLL. You just need to select a -dll config from the list of project +configs and you're fine. + +NOTE: Theoretically, assimp-dll can be used with multithreaded (non-dll) runtime libraries, +as long as you don't utilize any non-public stuff from the code folder. However, if you happen +to encounter *very* strange problems, try changing the runtime to Multithreaded (Debug) DLL. + +@section assimp_stlport Building against STLport + +STLport is a free, fast and secure STL replacement that works with +all major compilers and platforms. To get it, download the latest release from +. +Usually you'll just need to run 'configure' + a makefile (see their README for more details). +Don't miss to add /stlport to your compiler's default include paths - prior +to the directory where your compiler vendor's headers lie. Do the same for /lib and +recompile assimp. To ensure you're really building against STLport see aiGetCompileFlags(). +
+In our testing, STLport builds tend to be a bit faster than builds against Microsoft's +C++ Standard Library. + +*/ + + +/** +@page usage Usage + +@section access_cpp Access by C++ class interface + +The assimp library can be accessed by both a class or flat function interface. The C++ class +interface is the preferred way of interaction: you create an instance of class Assimp::Importer, +maybe adjust some settings of it and then call Assimp::Importer::ReadFile(). The class will +read the files and process its data, handing back the imported data as a pointer to an aiScene +to you. You can now extract the data you need from the file. The importer manages all the resources +for itsself. If the importer is destroyed, all the data that was created/read by it will be +destroyed, too. So the easiest way to use the Importer is to create an instance locally, use its +results and then simply let it go out of scope. + +C++ example: +@code +#include // C++ importer interface +#include // Output data structure +#include // Post processing flags + +bool DoTheImportThing( const std::string& pFile) +{ + // Create an instance of the Importer class + Assimp::Importer importer; + + // And have it read the given file with some example postprocessing + // Usually - if speed is not the most important aspect for you - you'll + // propably to request more postprocessing than we do in this example. + const aiScene* scene = importer.ReadFile( pFile, + aiProcess_CalcTangentSpace | + aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_SortByPType); + + // If the import failed, report it + if( !scene) + { + DoTheErrorLogging( importer.GetErrorString()); + return false; + } + + // Now we can access the file's contents. + DoTheSceneProcessing( scene); + + // We're done. Everything will be cleaned up by the importer destructor + return true; +} +@endcode + +What exactly is read from the files and how you interpret it is described at the @ref data page. @endlink The post processing steps that the assimp library can apply to the +imported data are listed at #aiPostProcessSteps. See the @ref pp Post proccessing page for more details. + +Note that the aiScene data structure returned is declared 'const'. Yes, you can get rid of +these 5 letters with a simple cast. Yes, you may do that. No, it's not recommended (and it's +suicide in DLL builds if you try to use new or delete on any of the arrays in the scene). + +@section access_c Access by plain-c function interface + +The plain function interface is just as simple, but requires you to manually call the clean-up +after you're done with the imported data. To start the import process, call aiImportFile() +with the filename in question and the desired postprocessing flags like above. If the call +is successful, an aiScene pointer with the imported data is handed back to you. When you're +done with the extraction of the data you're interested in, call aiReleaseImport() on the +imported scene to clean up all resources associated with the import. + +C example: +@code +#include // Plain-C interface +#include // Output data structure +#include // Post processing flags + +bool DoTheImportThing( const char* pFile) +{ + // Start the import on the given file with some example postprocessing + // Usually - if speed is not the most important aspect for you - you'll t + // probably to request more postprocessing than we do in this example. + const aiScene* scene = aiImportFile( pFile, + aiProcess_CalcTangentSpace | + aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_SortByPType); + + // If the import failed, report it + if( !scene) + { + DoTheErrorLogging( aiGetErrorString()); + return false; + } + + // Now we can access the file's contents + DoTheSceneProcessing( scene); + + // We're done. Release all resources associated with this import + aiReleaseImport( scene); + return true; +} +@endcode + +@section custom_io Using custom IO logic with the C++ class interface + +The assimp library needs to access files internally. This of course applies to the file you want +to read, but also to additional files in the same folder for certain file formats. By default, +standard C/C++ IO logic is used to access these files. If your application works in a special +environment where custom logic is needed to access the specified files, you have to supply +custom implementations of IOStream and IOSystem. A shortened example might look like this: + +@code +#include +#include + +// My own implementation of IOStream +class MyIOStream : public Assimp::IOStream +{ + friend class MyIOSystem; + +protected: + // Constructor protected for private usage by MyIOSystem + MyIOStream(void); + +public: + ~MyIOStream(void); + size_t Read( void* pvBuffer, size_t pSize, size_t pCount) { ... } + size_t Write( const void* pvBuffer, size_t pSize, size_t pCount) { ... } + aiReturn Seek( size_t pOffset, aiOrigin pOrigin) { ... } + size_t Tell() const { ... } + size_t FileSize() const { ... } + void Flush () { ... } +}; + +// Fisher Price - My First Filesystem +class MyIOSystem : public Assimp::IOSystem +{ + MyIOSystem() { ... } + ~MyIOSystem() { ... } + + // Check whether a specific file exists + bool Exists( const std::string& pFile) const { + .. + } + + // Get the path delimiter character we'd like to see + char GetOsSeparator() const { + return '/'; + } + + // ... and finally a method to open a custom stream + IOStream* Open( const std::string& pFile, const std::string& pMode) { + return new MyIOStream( ... ); + } + + void Close( IOStream* pFile) { delete pFile; } +}; +@endcode + +Now that your IO system is implemented, supply an instance of it to the Importer object by calling +Assimp::Importer::SetIOHandler(). + +@code +void DoTheImportThing( const std::string& pFile) +{ + Assimp::Importer importer; + // put my custom IO handling in place + importer.SetIOHandler( new MyIOSystem()); + + // the import process will now use this implementation to access any file + importer.ReadFile( pFile, SomeFlag | SomeOtherFlag); +} +@endcode + + +@section custom_io_c Using custom IO logic with the plain-c function interface + +The C interface also provides a way to override the file system. Control is not as fine-grained as for C++ although +surely enough for almost any purpose. The process is simple: + +
    +
  • Include cfileio.h +
  • Fill an aiFileIO structure with custom file system callbacks (they're self-explanatory as they work similar to the CRT's fXXX functions) +
  • .. and pass it as parameter to #aiImportFileEx +
+ +@section logging Logging + +The assimp library provides an easy mechanism to log messages. For instance if you want to check the state of your +import and you just want to see, after which preprocessing step the import-process was aborted you can take a look +into the log. +Per default the assimp-library provides a default log implementation, where you can log your user specific message +by calling it as a singleton with the requested logging-type. To see how this works take a look to this: + +@code +using namespace Assimp; + +// Create a logger instance +DefaultLogger::create("",Logger::VERBOSE); + +// Now I am ready for logging my stuff +DefaultLogger::get()->info("this is my info-call"); + +// Kill it after the work is done +DefaultLogger::kill(); +@endcode + +At first you have to create the default-logger-instance (create). Now you are ready to rock and can log a +little bit around. After that you should kill it to release the singleton instance. + +If you want to integrate the assimp-log into your own GUI it my be helpful to have a mechanism writing +the logs into your own log windows. The logger interface provides this by implementing an interface called LogStream. +You can attach and detach this log stream to the default-logger instance or any implementation derived from Logger. +Just derivate your own logger from the abstract base class LogStream and overwrite the write-method: + +@code +// Example stream +class myStream : + public LogStream +{ +public: + // Constructor + myStream() + { + // empty + } + + // Destructor + ~myStream() + { + // empty + } + + // Write womethink using your own functionality + void write(const char* message) + { + ::printf("%s\n", message); + } +}; + +// Select the kinds of messages you want to receive on this log stream +const unsigned int severity = Logger::DEBUGGING|Logger::INFO|Logger::ERR|Logger::WARN; + +// Attaching it to the default logger +Assimp::DefaultLogger::get()->attachStream( new myStream(), severity ); + +@endcode + +The severity level controls the kind of message which will be written into +the attached stream. If you just want to log errors and warnings set the warn +and error severity flag for those severities. It is also possible to remove +a self defined logstream from an error severity by detaching it with the severity +flag set: + +@code + +unsigned int severity = 0; +severity |= Logger::DEBUGGING; + +// Detach debug messages from you self defined stream +Assimp::DefaultLogger::get()->attachStream( new myStream(), severity ); + +@endcode + +If you want to implement your own logger just derive from the abstract base class +#Logger and overwrite the methods debug, info, warn and error. + +If you want to see the debug-messages in a debug-configured build, the Logger-interface +provides a logging-severity. You can set it calling the following method: + +@code + +Assimp::DefaultLogger::get()->setLogSeverity( LogSeverity log_severity ); + +@endcode + +The normal logging severity supports just the basic stuff like, info, warnings and errors. +In the verbose level very fine-grained debug messages will be logged, too. Note that this +kind kind of logging might decrease import performance. +*/ + +/** +@page data Data Structures + +The assimp library returns the imported data in a collection of structures. aiScene forms the root +of the data, from here you gain access to all the nodes, meshes, materials, animations or textures +that were read from the imported file. The aiScene is returned from a successful call to +assimp::Importer::ReadFile(), aiImportFile() or aiImportFileEx() - see the @link usage Usage page @endlink +for further information on how to use the library. + +By default, all 3D data is provided in a right-handed coordinate system such as OpenGL uses. In +this coordinate system, +X points to the right, -Z points away from the viewer into the screen and ++Y points upwards. Several modeling packages such as 3D Studio Max use this coordinate system as well (or a rotated variant of it). +By contrast, some other environments use left-handed coordinate systems, a prominent example being +DirectX. If you need the imported data to be in a left-handed coordinate system, supply the +#aiProcess_MakeLeftHanded flag to the ReadFile() function call. + +The output face winding is counter clockwise. Use #aiProcess_FlipWindingOrder to get CW data. +@code +x2 + + x1 + x0 +@endcode + +Outputted polygons can be literally everything: they're probably concave, self-intersecting or non-planar, +although our built-in triangulation (#aiProcess_Triangulate postprocessing step) doesn't handle the two latter. + +The output UV coordinate system has its origin in the lower-left corner: +@code +0y|1y ---------- 1x|1y + | | + | | + | | +0x|0y ---------- 1x|0y +@endcode +Use the #aiProcess_FlipUVs flag to get UV coordinates with the upper-left corner als origin. + +All matrices in the library are row-major. That means that the matrices are stored row by row in memory, +which is similar to the OpenGL matrix layout. A typical 4x4 matrix including a translational part looks like this: +@code +X1 Y1 Z1 T1 +X2 Y2 Z2 T2 +X3 Y3 Z3 T3 +0 0 0 1 +@endcode + +... with (X1, X2, X3) being the X base vector, (Y1, Y2, Y3) being the Y base vector, (Z1, Z2, Z3) +being the Z base vector and (T1, T2, T3) being the translation part. If you want to use these matrices +in DirectX functions, you have to transpose them. + +
+ +11.24.09: We changed the orientation of our quaternions to the most common convention to avoid confusion. +However, if you're a previous user of Assimp and you update the library to revisions beyond SVNREV 502, +you have to adapt your animation loading code to match the new quaternion orientation. + +
+ +@section hierarchy The Node Hierarchy + +Nodes are little named entities in the scene that have a place and orientation relative to their parents. +Starting from the scene's root node all nodes can have 0 to x child nodes, thus forming a hierarchy. +They form the base on which the scene is built on: a node can refer to 0..x meshes, can be referred to +by a bone of a mesh or can be animated by a key sequence of an animation. DirectX calls them "frames", +others call them "objects", we call them aiNode. + +A node can potentially refer to single or multiple meshes. The meshes are not stored inside the node, but +instead in an array of aiMesh inside the aiScene. A node only refers to them by their array index. This also means +that multiple nodes can refer to the same mesh, which provides a simple form of instancing. A mesh referred to +by this way lives in the node's local coordinate system. If you want the mesh's orientation in global +space, you'd have to concatenate the transformations from the referring node and all of its parents. + +Most of the file formats don't really support complex scenes, though, but a single model only. But there are +more complex formats such as .3ds, .x or .collada scenes which may contain an arbitrary complex +hierarchy of nodes and meshes. I for myself would suggest a recursive filter function such as the +following pseudocode: + +@code +void CopyNodesWithMeshes( aiNode node, SceneObject targetParent, Matrix4x4 accTransform) +{ + SceneObject parent; + Matrix4x4 transform; + + // if node has meshes, create a new scene object for it + if( node.mNumMeshes > 0) + { + SceneObjekt newObject = new SceneObject; + targetParent.addChild( newObject); + // copy the meshes + CopyMeshes( node, newObject); + + // the new object is the parent for all child nodes + parent = newObject; + transform.SetUnity(); + } else + { + // if no meshes, skip the node, but keep its transformation + parent = targetParent; + transform = node.mTransformation * accTransform; + } + + // continue for all child nodes + for( all node.mChildren) + CopyNodesWithMeshes( node.mChildren[a], parent, transform); +} +@endcode + +This function copies a node into the scene graph if it has children. If yes, a new scene object +is created for the import node and the node's meshes are copied over. If not, no object is created. +Potential child objects will be added to the old targetParent, but there transformation will be correct +in respect to the global space. This function also works great in filtering the bone nodes - nodes +that form the bone hierarchy for another mesh/node, but don't have any mesh themselves. + +@section meshes Meshes + +All meshes of an imported scene are stored in an array of aiMesh* inside the aiScene. Nodes refer +to them by their index in the array and providing the coordinate system for them, too. One mesh uses +only a single material everywhere - if parts of the model use a different material, this part is +moved to a separate mesh at the same node. The mesh refers to its material in the same way as the +node refers to its meshes: materials are stored in an array inside aiScene, the mesh stores only +an index into this array. + +An aiMesh is defined by a series of data channels. The presence of these data channels is defined +by the contents of the imported file: by default there are only those data channels present in the mesh +that were also found in the file. The only channels guarenteed to be always present are aiMesh::mVertices +and aiMesh::mFaces. You can test for the presence of other data by testing the pointers against NULL +or use the helper functions provided by aiMesh. You may also specify several post processing flags +at Importer::ReadFile() to let assimp calculate or recalculate additional data channels for you. + +At the moment, a single aiMesh may contain a set of triangles and polygons. A single vertex does always +have a position. In addition it may have one normal, one tangent and bitangent, zero to AI_MAX_NUMBER_OF_TEXTURECOORDS +(4 at the moment) texture coords and zero to AI_MAX_NUMBER_OF_COLOR_SETS (4) vertex colors. In addition +a mesh may or may not have a set of bones described by an array of aiBone structures. How to interpret +the bone information is described later on. + +@section material Materials + +See the @link materials Material System Page. @endlink + +@section bones Bones + +A mesh may have a set of bones in the form of aiBone structures.. Bones are a means to deform a mesh +according to the movement of a skeleton. Each bone has a name and a set of vertices on which it has influence. +Its offset matrix declares the transformation needed to transform from mesh space to the local space of this bone. + +Using the bones name you can find the corresponding node in the node hierarchy. This node in relation +to the other bones' nodes defines the skeleton of the mesh. Unfortunately there might also be +nodes which are not used by a bone in the mesh, but still affect the pose of the skeleton because +they have child nodes which are bones. So when creating the skeleton hierarchy for a mesh I +suggest the following method: + +a) Create a map or a similar container to store which nodes are necessary for the skeleton. +Pre-initialise it for all nodes with a "no".
+b) For each bone in the mesh:
+b1) Find the corresponding node in the scene's hierarchy by comparing their names.
+b2) Mark this node as "yes" in the necessityMap.
+b3) Mark all of its parents the same way until you 1) find the mesh's node or 2) the parent of the mesh's node.
+c) Recursively iterate over the node hierarchy
+c1) If the node is marked as necessary, copy it into the skeleton and check its children
+c2) If the node is marked as not necessary, skip it and do not iterate over its children.
+ +Reasons: you need all the parent nodes to keep the transformation chain intact. For most +file formats and modelling packages the node hierarchy of the skeleton is either a child +of the mesh node or a sibling of the mesh node but this is by no means a requirement so you shouldn't rely on it. +The node closest to the root node is your skeleton root, from there you +start copying the hierarchy. You can skip every branch without a node being a bone in the mesh - +that's why the algorithm skips the whole branch if the node is marked as "not necessary". + +You should now have a mesh in your engine with a skeleton that is a subset of the imported hierarchy. + +@section anims Animations + +An imported scene may contain zero to x aiAnimation entries. An animation in this context is a set +of keyframe sequences where each sequence describes the orientation of a single node in the hierarchy +over a limited time span. Animations of this kind are usually used to animate the skeleton of +a skinned mesh, but there are other uses as well. + +An aiAnimation has a duration. The duration as well as all time stamps are given in ticks. To get +the correct timing, all time stamp thus have to be divided by aiAnimation::mTicksPerSecond. Beware, +though, that certain combinations of file format and exporter don't always store this information +in the exported file. In this case, mTicksPerSecond is set to 0 to indicate the lack of knowledge. + +The aiAnimation consists of a series of aiNodeAnim's. Each bone animation affects a single node in +the node hierarchy only, the name specifying which node is affected. For this node the structure +stores three separate key sequences: a vector key sequence for the position, a quaternion key sequence +for the rotation and another vector key sequence for the scaling. All 3d data is local to the +coordinate space of the node's parent, that means in the same space as the node's transformation matrix. +There might be cases where animation tracks refer to a non-existent node by their name, but this +should not be the case in your every-day data. + +To apply such an animation you need to identify the animation tracks that refer to actual bones +in your mesh. Then for every track:
+a) Find the keys that lay right before the current anim time.
+b) Optional: interpolate between these and the following keys.
+c) Combine the calculated position, rotation and scaling to a tranformation matrix
+d) Set the affected node's transformation to the calculated matrix.
+ +If you need hints on how to convert to or from quaternions, have a look at the +Matrix&Quaternion FAQ. I suggest +using logarithmic interpolation for the scaling keys if you happen to need them - usually you don't +need them at all. + +@section textures Textures + +Normally textures used by assets are stored in separate files, however, +there are file formats embedding their textures directly into the model file. +Such textures are loaded into an aiTexture structure. +
+There are two cases: +
+1) The texture is NOT compressed. Its color data is directly stored +in the aiTexture structure as an array of aiTexture::mWidth * aiTexture::mHeight aiTexel structures. Each aiTexel represents a pixel (or "texel") of the texture +image. The color data is stored in an unsigned RGBA8888 format, which can be easily used for +both Direct3D and OpenGL (swizzling the order of the color components might be necessary). +RGBA8888 has been chosen because it is well-known, easy to use and natively +supported by nearly all graphics APIs. +
+2) This applies if aiTexture::mHeight == 0 is fullfilled. Then, texture is stored in a +"compressed" format such as DDS or PNG. The term "compressed" does not mean that the +texture data must actually be compressed, however the texture was found in the +model file as if it was stored in a separate file on the harddisk. Appropriate +decoders (such as libjpeg, libpng, D3DX, DevIL) are required to load theses textures. +aiTexture::mWidth specifies the size of the texture data in bytes, aiTexture::pcData is +a pointer to the raw image data and aiTexture::achFormatHint is either zeroed or +contains the most common file extension of the embedded texture's format. This value is only +set if assimp is able to determine the file format. +*/ + + +/** +@page materials Material System + +@section General Overview +All materials are stored in an array of aiMaterial inside the aiScene. + +Each aiMesh refers to one +material by its index in the array. Due to the vastly diverging definitions and usages of material +parameters there is no hard definition of a material structure. Instead a material is defined by +a set of properties accessible by their names. Have a look at assimp/material.h to see what types of +properties are defined. In this file there are also various functions defined to test for the +presence of certain properties in a material and retrieve their values. + +@section mat_tex Textures + +Textures are organized in stacks, each stack being evaluated independently. The final color value from a particular texture stack is used in the shading equation. For example, the computed color value of the diffuse texture stack (aiTextureType_DIFFUSE) is multipled with the amount of incoming diffuse light to obtain the final diffuse color of a pixel. + +@code + + Stack Resulting equation + +------------------------ +| Constant base color | color +------------------------ +| Blend operation 0 | + +------------------------ +| Strength factor 0 | 0.25* +------------------------ +| Texture 0 | texture_0 +------------------------ +| Blend operation 1 | * +------------------------ +| Strength factor 1 | 1.0* +------------------------ +| Texture 1 | texture_1 +------------------------ + ... ... + +@endcode + +@section keys Constants + +All material key constants start with 'AI_MATKEY' (it's an ugly macro for historical reasons, don't ask). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameData TypeDefault ValueMeaningNotes
NAMEaiStringn/aThe name of the material, if available. Ignored by aiProcess_RemoveRedundantMaterials. Materials are considered equal even if their names are different.
COLOR_DIFFUSEaiColor3Dblack (0,0,0)Diffuse color of the material. This is typically scaled by the amount of incoming diffuse light (e.g. using gouraud shading) ---
COLOR_SPECULARaiColor3Dblack (0,0,0)Specular color of the material. This is typically scaled by the amount of incoming specular light (e.g. using phong shading) ---
COLOR_AMBIENTaiColor3Dblack (0,0,0)Ambient color of the material. This is typically scaled by the amount of ambient light ---
COLOR_EMISSIVEaiColor3Dblack (0,0,0)Emissive color of the material. This is the amount of light emitted by the object. In real time applications it will usually not affect surrounding objects, but raytracing applications may wish to treat emissive objects as light sources. ---
COLOR_TRANSPARENTaiColor3Dblack (0,0,0)Defines the transparent color of the material, this is the color to be multiplied with the color of + translucent light to construct the final 'destination color' for a particular position in the screen buffer. T ---
WIREFRAMEintfalseSpecifies whether wireframe rendering must be turned on for the material. 0 for false, !0 for true. ---
TWOSIDEDintfalseSpecifies whether meshes using this material must be rendered without backface culling. 0 for false, !0 for true. Some importers set this property if they don't know whether the output face oder is right. As long as it is not set, you may safely enable backface culling.
SHADING_MODELintgouraudOne of the #aiShadingMode enumerated values. Defines the library shading model to use for (real time) rendering to approximate the original look of the material as closely as possible. The presence of this key might indicate a more complex material. If absent, assume phong shading only if a specular exponent is given.
BLEND_FUNCintfalseOne of the #aiBlendMode enumerated values. Defines how the final color value in the screen buffer is computed from the given color at that position and the newly computed color from the material. Simply said, alpha blending settings.-
OPACITYfloat1.0Defines the opacity of the material in a range between 0..1.Use this value to decide whether you have to activate alpha blending for rendering. OPACITY != 1 usually also implies TWOSIDED=1 to avoid cull artifacts.
SHININESSfloat0.fDefines the shininess of a phong-shaded material. This is actually the exponent of the phong specular equationSHININESS=0 is equivalent to SHADING_MODEL=aiShadingMode_Gouraud.
SHININESS_STRENGTHfloat1.0Scales the specular color of the material.This value is kept separate from the specular color by most modelers, and so do we.
REFRACTIfloat1.0Defines the Index Of Refraction for the material. That's not supported by most file formats.Might be of interest for raytracing.
TEXTURE(t,n)aiStringn/aDefines the path to the n'th texture on the stack 't', where 'n' is any value >= 0 and 't' is one of the #aiTextureType enumerated values.See the 'Textures' section above.
TEXBLEND(t,n)floatn/aDefines the strength the n'th texture on the stack 't'. All color components (rgb) are multipled with this factor *before* any further processing is done.-
TEXOP(t,n)intn/aOne of the #aiTextureOp enumerated values. Defines the arithmetic operation to be used to combine the n'th texture on the stack 't' with the n-1'th. TEXOP(t,0) refers to the blend operation between the base color for this stack (e.g. COLOR_DIFFUSE for the diffuse stack) and the first texture.-
MAPPING(t,n)intn/aDefines how the input mapping coordinates for sampling the n'th texture on the stack 't' are computed. Usually explicit UV coordinates are provided, but some model file formats might also be using basic shapes, such as spheres or cylinders, to project textures onto meshes.See the 'Textures' section below. #aiProcess_GenUVCoords can be used to let Assimp compute proper UV coordinates from projective mappings.
UVWSRC(t,n)intn/aDefines the UV channel to be used as input mapping coordinates for sampling the n'th texture on the stack 't'. All meshes assigned to this material share the same UV channel setupPresence of this key implies MAPPING(t,n) to be #aiTextureMapping_UV. See @ref uvwsrc for more details.
MAPPINGMODE_U(t,n)intn/aAny of the #aiTextureMapMode enumerated values. Defines the texture wrapping mode on the x axis for sampling the n'th texture on the stack 't'. 'Wrapping' occurs whenever UVs lie outside the 0..1 range. -
MAPPINGMODE_V(t,n)intn/aWrap mode on the v axis. See MAPPINGMODE_U. -
TEXMAP_AXIS(t,n)aiVector3Dn/a Defines the base axis to to compute the mapping coordinates for the n'th texture on the stack 't' from. This is not required for UV-mapped textures. For instance, if MAPPING(t,n) is #aiTextureMapping_SPHERE, U and V would map to longitude and latitude of a sphere around the given axis. The axis is given in local mesh space.-
TEXFLAGS(t,n)intn/a Defines miscellaneous flag for the n'th texture on the stack 't'. This is a bitwise combination of the #aiTextureFlags enumerated values.-
+ +@section cpp C++-API + +Retrieving a property from a material is done using various utility functions. For C++ it's simply calling aiMaterial::Get() + +@code + +aiMaterial* mat = ..... + +// The generic way +if(AI_SUCCESS != mat->Get(,)) { + // handle epic failure here +} + +@endcode + +Simple, isn't it? To get the name of a material you would use + +@code + +aiString name; +mat->Get(AI_MATKEY_NAME,name); + +@endcode + +Or for the diffuse color ('color' won't be modified if the property is not set) + +@code + +aiColor3D color (0.f,0.f,0.f); +mat->Get(AI_MATKEY_COLOR_DIFFUSE,color); + +@endcode + +Note: Get() is actually a template with explicit specializations for aiColor3D, aiColor4D, aiString, float, int and some others. +Make sure that the type of the second parameter matches the expected data type of the material property (no compile-time check yet!). +Don't follow this advice if you wish to encounter very strange results. + +@section C C-API + +For good old C it's slightly different. Take a look at the aiGetMaterialGet functions. + +@code + +aiMaterial* mat = ..... + +if(AI_SUCCESS != aiGetMaterialFloat(mat,,)) { + // handle epic failure here +} + +@endcode + +To get the name of a material you would use + +@code + +aiString name; +aiGetMaterialString(mat,AI_MATKEY_NAME,&name); + +@endcode + +Or for the diffuse color ('color' won't be modified if the property is not set) + +@code + +aiColor3D color (0.f,0.f,0.f); +aiGetMaterialColor(mat,AI_MATKEY_COLOR_DIFFUSE,&color); + +@endcode + +@section uvwsrc How to map UV channels to textures (MATKEY_UVWSRC) + +The MATKEY_UVWSRC property is only present if the source format doesn't specify an explicit mapping from +textures to UV channels. Many formats don't do this and assimp is not aware of a perfect rule either. + +Your handling of UV channels needs to be flexible therefore. Our recommendation is to use logic like this +to handle most cases properly: + +@verbatim +have only one uv channel? + assign channel 0 to all textures and break + +for all textures + have uvwsrc for this texture? + assign channel specified in uvwsrc + else + assign channels in ascending order for all texture stacks, + i.e. diffuse1 gets channel 1, opacity0 gets channel 0. + +@endverbatim + +@section pseudo Pseudo Code Listing + +For completeness, the following is a very rough pseudo-code sample showing how to evaluate Assimp materials in your +shading pipeline. You'll probably want to limit your handling of all those material keys to a reasonable subset suitable for your purposes +(for example most 3d engines won't support highly complex multi-layer materials, but many 3d modellers do). + +Also note that this sample is targeted at a (shader-based) rendering pipeline for real time graphics. + +@code + +// --------------------------------------------------------------------------------------- +// Evaluate multiple textures stacked on top of each other +float3 EvaluateStack(stack) +{ + // For the 'diffuse' stack stack.base_color would be COLOR_DIFFUSE + // and TEXTURE(aiTextureType_DIFFUSE,n) the n'th texture. + + float3 base = stack.base_color; + for (every texture in stack) + { + // assuming we have explicit & pretransformed UVs for this texture + float3 color = SampleTexture(texture,uv); + + // scale by texture blend factor + color *= texture.blend; + + if (texture.op == add) + base += color; + else if (texture.op == multiply) + base *= color; + else // other blend ops go here + } + return base; +} + +// --------------------------------------------------------------------------------------- +// Compute the diffuse contribution for a pixel +float3 ComputeDiffuseContribution() +{ + if (shading == none) + return float3(1,1,1); + + float3 intensity (0,0,0); + for (all lights in range) + { + float fac = 1.f; + if (shading == gouraud) + fac = lambert-term .. + else // other shading modes go here + + // handling of different types of lights, such as point or spot lights + // ... + + // and finally sum the contribution of this single light ... + intensity += light.diffuse_color * fac; + } + // ... and combine the final incoming light with the diffuse color + return EvaluateStack(diffuse) * intensity; +} + +// --------------------------------------------------------------------------------------- +// Compute the specular contribution for a pixel +float3 ComputeSpecularContribution() +{ + if (shading == gouraud || specular_strength == 0 || specular_exponent == 0) + return float3(0,0,0); + + float3 intensity (0,0,0); + for (all lights in range) + { + float fac = 1.f; + if (shading == phong) + fac = phong-term .. + else // other specular shading modes go here + + // handling of different types of lights, such as point or spot lights + // ... + + // and finally sum the specular contribution of this single light ... + intensity += light.specular_color * fac; + } + // ... and combine the final specular light with the specular color + return EvaluateStack(specular) * intensity * specular_strength; +} + +// --------------------------------------------------------------------------------------- +// Compute the ambient contribution for a pixel +float3 ComputeAmbientContribution() +{ + if (shading == none) + return float3(0,0,0); + + float3 intensity (0,0,0); + for (all lights in range) + { + float fac = 1.f; + + // handling of different types of lights, such as point or spot lights + // ... + + // and finally sum the ambient contribution of this single light ... + intensity += light.ambient_color * fac; + } + // ... and combine the final ambient light with the ambient color + return EvaluateStack(ambient) * intensity; +} + +// --------------------------------------------------------------------------------------- +// Compute the final color value for a pixel +// @param prev Previous color at that position in the framebuffer +float4 PimpMyPixel (float4 prev) +{ + // .. handle displacement mapping per vertex + // .. handle bump/normal mapping + + // Get all single light contribution terms + float3 diff = ComputeDiffuseContribution(); + float3 spec = ComputeSpecularContribution(); + float3 ambi = ComputeAmbientContribution(); + + // .. and compute the final color value for this pixel + float3 color = diff + spec + ambi; + float3 opac = EvaluateStack(opacity); + + // note the *slightly* strange meaning of additive and multiplicative blending here ... + // those names will most likely be changed in future versions + if (blend_func == add) + return prev+color*opac; + else if (blend_func == multiply) + return prev*(1.0-opac)+prev*opac; + + return color; +} + +@endcode + +*/ + + + + +/** +@page perf Performance + +@section perf_overview Overview + +This page discusses general performance issues related to assimp. + +@section perf_profile Profiling + +assimp has built-in support for very basic profiling and time measurement. To turn it on, set the GLOB_MEASURE_TIME +configuration switch to true (nonzero). Results are dumped to the log file, so you need to setup +an appropriate logger implementation with at least one output stream first (see the @link logging Logging Page @endlink +for the details.). + +Note that these measurements are based on a single run of the importer and each of the post processing steps, so +a single result set is far away from being significant in a statistic sense. While precision can be improved +by running the test multiple times, the low accuracy of the timings may render the results useless +for smaller files. + +A sample report looks like this (some unrelated log messages omitted, entries grouped for clarity): + +@verbatim +Debug, T5488: START `total` +Info, T5488: Found a matching importer for this file format + + +Debug, T5488: START `import` +Info, T5488: BlendModifier: Applied the `Subdivision` modifier to `OBMonkey` +Debug, T5488: END `import`, dt= 3.516 s + + +Debug, T5488: START `preprocess` +Debug, T5488: END `preprocess`, dt= 0.001 s +Info, T5488: Entering post processing pipeline + + +Debug, T5488: START `postprocess` +Debug, T5488: RemoveRedundantMatsProcess begin +Debug, T5488: RemoveRedundantMatsProcess finished +Debug, T5488: END `postprocess`, dt= 0.001 s + + +Debug, T5488: START `postprocess` +Debug, T5488: TriangulateProcess begin +Info, T5488: TriangulateProcess finished. All polygons have been triangulated. +Debug, T5488: END `postprocess`, dt= 3.415 s + + +Debug, T5488: START `postprocess` +Debug, T5488: SortByPTypeProcess begin +Info, T5488: Points: 0, Lines: 0, Triangles: 1, Polygons: 0 (Meshes, X = removed) +Debug, T5488: SortByPTypeProcess finished + +Debug, T5488: START `postprocess` +Debug, T5488: JoinVerticesProcess begin +Debug, T5488: Mesh 0 (unnamed) | Verts in: 503808 out: 126345 | ~74.922 +Info, T5488: JoinVerticesProcess finished | Verts in: 503808 out: 126345 | ~74.9 +Debug, T5488: END `postprocess`, dt= 2.052 s + +Debug, T5488: START `postprocess` +Debug, T5488: FlipWindingOrderProcess begin +Debug, T5488: FlipWindingOrderProcess finished +Debug, T5488: END `postprocess`, dt= 0.006 s + + +Debug, T5488: START `postprocess` +Debug, T5488: LimitBoneWeightsProcess begin +Debug, T5488: LimitBoneWeightsProcess end +Debug, T5488: END `postprocess`, dt= 0.001 s + + +Debug, T5488: START `postprocess` +Debug, T5488: ImproveCacheLocalityProcess begin +Debug, T5488: Mesh 0 | ACMR in: 0.851622 out: 0.718139 | ~15.7 +Info, T5488: Cache relevant are 1 meshes (251904 faces). Average output ACMR is 0.718139 +Debug, T5488: ImproveCacheLocalityProcess finished. +Debug, T5488: END `postprocess`, dt= 1.903 s + + +Info, T5488: Leaving post processing pipeline +Debug, T5488: END `total`, dt= 11.269 s +@endverbatim + +In this particular example only one fourth of the total import time was spent on the actual importing, while the rest of the +time got consumed by the #aiProcess_Triangulate, #aiProcess_JoinIdenticalVertices and #aiProcess_ImproveCacheLocality +postprocessing steps. A wise selection of postprocessing steps is therefore essential to getting good performance. +Of course this depends on the individual requirements of your application, in many of the typical use cases of assimp performance won't +matter (i.e. in an offline content pipeline). +*/ + +/** +@page threading Threading + +@section overview Overview + +This page discusses both assimps scalability in threaded environments and the precautions to be taken in order to +use it from multiple threads concurrently. + +@section threadsafety Thread-safety / using Assimp concurrently from several threads + +The library can be accessed by multiple threads simultaneously, as long as the +following prerequisites are fulfilled: + + - Users of the C++-API should ensure that they use a dedicated #Assimp::Importer instance for each thread. Constructing instances of #Assimp::Importer is expensive, so it might be a good idea to + let every thread maintain its own thread-local instance (which can be used to + load as many files as necessary). + - The C-API is thread safe. + - When supplying custom IO logic, one must make sure the underlying implementation is thread-safe. + - Custom log streams or logger replacements have to be thread-safe, too. + + + + +Multiple concurrent imports may or may not be beneficial, however. For certain file formats in conjunction with +little or no post processing IO times tend to be the performance bottleneck. Intense post processing together +with 'slow' file formats like X or Collada might scale well with multiple concurrent imports. + + +@section automt Internal threading + +Internal multi-threading is not currently implemented. +*/ + +/** +@page res Resources + +This page lists some useful resources for assimp. Note that, even though the core team has an eye on them, +we cannot guarantee the accuracy of third-party information. If in doubt, it's best to ask either on the +mailing list or on our forums on SF.net. + + - assimp comes with some sample applications, these can be found in the ./samples folder. Don't forget to read the README file. + - http://www.drivenbynostalgia.com/files/AssimpOpenGLDemo.rar - OpenGl animation sample using the library's animation import facilities. + - http://nolimitsdesigns.com/game-design/open-asset-import-library-animation-loader/ is another utility to + simplify animation playback. + - http://ogldev.atspace.co.uk/www/tutorial22/tutorial22.html - Tutorial "Loading models using the Open Asset Import Library", out of a series of OpenGl tutorials. + +*/ + + +/** +@page importer_notes Importer Notes + +
+@section blender Blender + +This section contains implementation notes for the Blender3D importer. +@subsection bl_overview Overview + +assimp provides a self-contained reimplementation of Blender's so called SDNA system (http://www.blender.org/development/architecture/notes-on-sdna/). +SDNA allows Blender to be fully backward and forward compatible and to exchange +files across all platforms. The BLEND format is thus a non-trivial binary monster and the loader tries to read the most of it, +naturally limited by the scope of the #aiScene output data structure. +Consequently, if Blender is the only modeling tool in your asset work flow, consider writing a +custom exporter from Blender if assimps format coverage does not meet the requirements. + +@subsection bl_status Current status + +The Blender loader does not support animations yet, but is apart from that considered relatively stable. + +@subsection bl_notes Notes + +When filing bugs on the Blender loader, always give the Blender version (or, even better, post the file caused the error). + +
+@section ifc IFC + +This section contains implementation notes on the IFC-STEP importer. +@subsection ifc_overview Overview + +The library provides a partial implementation of the IFC2x3 industry standard for automatized exchange of CAE/architectural +data sets. See http://en.wikipedia.org/wiki/Industry_Foundation_Classes for more information on the format. We aim +at getting as much 3D data out of the files as possible. + +@subsection ifc_status Current status + +IFC support is new and considered experimental. Please report any bugs you may encounter. + +@subsection ifc_notes Notes + +- Only the STEP-based encoding is supported. IFCZIP and IFCXML are not (but IFCZIP can simply be unzipped to get a STEP file). +- The importer leaves vertex coordinates untouched, but applies a global scaling to the root transform to + convert from whichever unit the IFC file uses to metres. +- If multiple geometric representations are provided, the choice which one to load is based on how expensive a representation seems + to be in terms of import time. The loader also avoids representation types for which it has known deficits. +- Not supported are arbitrary binary operations (binary clipping is implemented, though). +- Of the various relationship types that IFC knows, only aggregation, containment and material assignment are resolved and mapped to + the output graph. +- The implementation knows only about IFC2X3 and applies this rule set to all models it encounters, + regardless of their actual version. Loading of older or newer files may fail with parsing errors. + +@subsection ifc_metadata Metadata + +IFC file properties (IfcPropertySet) are kept as per-node metadata, see aiNode::mMetaData. + +
+@section ogre Ogre +*ATTENTION*: The Ogre-Loader is currently under development, many things have changed after this documentation was written, but they are not final enough to rewrite the documentation. So things may have changed by now! + +This section contains implementations notes for the OgreXML importer. +@subsection overview Overview +Ogre importer is currently optimized for the Blender Ogre exporter, because thats the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922 + +@subsection what What will be loaded? + +Mesh: Faces, Positions, Normals and all TexCoords. The Materialname will be used to load the material. + +Material: The right material in the file will be searched, the importer should work with materials who +have 1 technique and 1 pass in this technique. From there, the texturename (for 1 color- and 1 normalmap) and the +materialcolors (but not in custom materials) will be loaded. Also, the materialname will be set. + +Skeleton: Skeleton with Bone hierarchy (Position and Rotation, but no Scaling in the skeleton is supported), names and transformations, +animations with rotation, translation and scaling keys. + +@subsection export_Blender How to export Files from Blender +You can find informations about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp +importer will load everything correctly: +- Use either "Rendering Material" or "Custom Material" see @ref material +- do not use "Flip Up Axies to Y" +- use "Skeleton name follow mesh" + + +@subsection xml XML Format +There is a binary and a XML mesh Format from Ogre. This loader can only +Handle xml files, but don't panic, there is a command line converter, which you can use +to create XML files from Binary Files. Just look on the Ogre page for it. + +Currently you can only load meshes. So you will need to import the *.mesh.xml file, the loader will +try to find the appendant material and skeleton file. + +The skeleton file must have the same name as the mesh file, e.g. fish.mesh.xml and fish.skeleton.xml. + +@subsection material Materials +The material file can have the same name as the mesh file (if the file is model.mesh or model.mesh.xml the +loader will try to load model.material), +or you can use Importer::Importer::SetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "materiafile.material") +to specify the name of the material file. This is especially usefull if multiply materials a stored in a single file. +The importer will first try to load the material with the same name as the mesh and only if this can't be open try +to load the alternate material file. The default material filename is "Scene.material". + +We suggest that you use custom materials, because they support multiple textures (like colormap and normalmap). First of all you +should read the custom material sektion in the Ogre Blender exporter Help File, and than use the assimp.tlp template, which you +can find in scripts/OgreImpoter/Assimp.tlp in the assimp source. If you don't set all values, don't worry, they will be ignored during import. + +If you want more properties in custom materials, you can easily expand the ogre material loader, it will be just a few lines for each property. +Just look in OgreImporterMaterial.cpp + +@subsection Importer Properties +- IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME: Normally, a texture is loaded as a colormap, if no + target is specified in the + materialfile. Is this switch is enabled, texture names ending with _n, _l, _s + are used as normalmaps, lightmaps or specularmaps. +
+ Property type: Bool. Default value: false. +- IMPORT_OGRE_MATERIAL_FILE: Ogre Meshes contain only the MaterialName, not the MaterialFile. + If there + is no material file with the same name as the material, Ogre Importer will + try to load this file and search the material in it. +
+ Property type: String. Default value: guessed. + +@subsection todo Todo +- Load colors in custom materials +- extend custom and normal material loading +- fix bone hierarchy bug +- test everything elaboratly +- check for non existent animation keys (what happens if a one time not all bones have a key?) +*/ + + +/** +@page extend Extending the Library + +@section General + +Or - how to write your own loaders. It's easy. You just need to implement the #Assimp::BaseImporter class, +which defines a few abstract methods, register your loader, test it carefully and provide test models for it. + +OK, that sounds too easy :-). The whole procedure for a new loader merely looks like this: + +
    +
  • Create a header (FormatNameImporter.h) and a unit (FormatNameImporter.cpp) in the <root>/code/ directory
  • +
  • Add them to the following workspaces: vc8 and vc9 (the files are in the workspaces directory), CMAKE (code/CMakeLists.txt, create a new +source group for your importer and put them also to ADD_LIBRARY( assimp SHARED))
  • +
  • Include AssimpPCH.h - this is the PCH file, and it includes already most Assimp-internal stuff.
  • +
  • Open Importer.cpp and include your header just below the (include_new_importers_here) line, +guarded by a #define +@code +#if (!defined assimp_BUILD_NO_FormatName_IMPORTER) + ... +#endif +@endcode +Wrap the same guard around your .cpp!
  • + +
  • Now advance to the (register_new_importers_here) line in the Importer.cpp and register your importer there - just like all the others do.
  • +
  • Setup a suitable test environment (i.e. use AssimpView or your own application), make sure to enable +the #aiProcess_ValidateDataStructure flag and enable verbose logging. That is, simply call before you import anything: +@code +DefaultLogger::create("AssimpLog.txt",Logger::VERBOSE) +@endcode +
  • +
  • +Implement the Assimp::BaseImporter::CanRead(), Assimp::BaseImporter::InternReadFile() and Assimp::BaseImporter::GetExtensionList(). +Just copy'n'paste the template from Appendix A and adapt it for your needs. +
  • +
  • For error handling, throw a dynamic allocated ImportErrorException (see Appendix A) for critical errors, and log errors, warnings, infos and debuginfos +with DefaultLogger::get()->[error, warn, debug, info]. +
  • +
  • +Make sure that your loader compiles against all build configurations on all supported platforms. This includes -noboost! To avoid problems, +see the boost section on this page for a list of all 'allowed' boost classes (again, this grew historically when we had to accept that boost +is not THAT widely spread that one could rely on it being available everywhere). +
  • +
  • +Provide some _free_ test models in <root>/test/models/<FormatName>/ and credit their authors. +Test files for a file format shouldn't be too large (~500 KiB in total), and not too repetive. Try to cover all format features with test data. +
  • +
  • +Done! Please, share your loader that everyone can profit from it! +
  • +
+ +@section properties Properties + +You can use properties to chance the behavior of you importer. In order to do so, you have to overide BaseImporter::SetupProperties, and specify +you custom properties in config.h. Just have a look to the other AI_CONFIG_IMPORT_* defines and you will understand, how it works. + +The properties can be set with Importer::SetProperty***() and can be accessed in your SetupProperties function with Importer::GetProperty***(). You can +store the properties as a member variable of your importer, they are thread safe. + +@section tnote Notes for text importers + +
    +
  • Try to make your parser as flexible as possible. Don't rely on particular layout, whitespace/tab style, +except if the file format has a strict definition, in which case you should always warn about spec violations. +But the general rule of thumb is be strict in what you write and tolerant in what you accept.
  • +
  • Call Assimp::BaseImporter::ConvertToUTF8() before you parse anything to convert foreign encodings to UTF-8. + That's not necessary for XML importers, which must use the provided IrrXML for reading.
  • +
+ +@section bnote Notes for binary importers + +
    +
  • +Take care of endianess issues! Assimp importers mostly support big-endian platforms, which define the AI_BUILD_BIG_ENDIAN constant. +See the next section for a list of utilities to simplify this task. +
  • +
  • +Don't trust the input data! Check all offsets! +
  • +
+ +@section util Utilities + +Mixed stuff for internal use by loaders, mostly documented (most of them are already included by AssimpPCH.h): +
    +
  • ByteSwapper (ByteSwapper.h) - manual byte swapping stuff for binary loaders.
  • +
  • StreamReader (StreamReader.h) - safe, endianess-correct, binary reading.
  • +
  • IrrXML (irrXMLWrapper.h) - for XML-parsing (SAX.
  • +
  • CommentRemover (RemoveComments.h) - remove single-line and multi-line comments from a text file.
  • +
  • fast_atof, strtoul10, strtoul16, SkipSpaceAndLineEnd, SkipToNextToken .. large family of low-level +parsing functions, mostly declared in fast_atof.h, StringComparison.h and ParsingUtils.h (a collection that grew +historically, so don't expect perfect organization).
  • +
  • ComputeNormalsWithSmoothingsGroups() (SmoothingGroups.h) - Computes normal vectors from plain old smoothing groups.
  • +
  • SkeletonMeshBuilder (SkeletonMeshBuilder.h) - generate a dummy mesh from a given (animation) skeleton.
  • +
  • StandardShapes (StandardShapes.h) - generate meshes for standard solids, such as platonic primitives, cylinders or spheres.
  • +
  • BatchLoader (BaseImporter.h) - manage imports from external files. Useful for file formats +which spread their data across multiple files.
  • +
  • SceneCombiner (SceneCombiner.h) - exhaustive toolset to merge multiple scenes. Useful for file formats +which spread their data across multiple files.
  • +
+ +@section mat Filling materials + +The required definitions zo set/remove/query keys in #aiMaterial structures are declared in MaterialSystem.h, in a +#aiMaterial derivate called #aiMaterial. The header is included by AssimpPCH.h, so you don't need to bother. + +@code +aiMaterial* mat = new aiMaterial(); + +const float spec = 16.f; +mat->AddProperty(&spec, 1, AI_MATKEY_SHININESS); + +//set the name of the material: +NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);//MaterialName is a std::string + +//set the first diffuse texture +NewMaterial->AddProperty(&aiString(Texturename.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));//again, Texturename is a std::string +@endcode + +@section boost Boost + +The boost whitelist: +
    +
  • boost.scoped_ptr
  • +
  • boost.scoped_array
  • +
  • boost.format
  • +
  • boost.random
  • +
  • boost.common_factor
  • +
  • boost.foreach
  • +
  • boost.tuple
  • +
+ +(if you happen to need something else, i.e. boost::thread, make this an optional feature. +assimp_BUILD_BOOST_WORKAROUND is defined for -noboost builds) + +@section appa Appendix A - Template for BaseImporter's abstract methods + +@code +// ------------------------------------------------------------------------------- +// Returns whether the class can handle the format of the given file. +bool xxxxImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, + bool checkSig) const +{ + const std::string extension = GetExtension(pFile); + if(extension == "xxxx") { + return true; + } + if (!extension.length() || checkSig) { + // no extension given, or we're called a second time because no + // suitable loader was found yet. This means, we're trying to open + // the file and look for and hints to identify the file format. + // #Assimp::BaseImporter provides some utilities: + // + // #Assimp::BaseImporter::SearchFileHeaderForToken - for text files. + // It reads the first lines of the file and does a substring check + // against a given list of 'magic' strings. + // + // #Assimp::BaseImporter::CheckMagicToken - for binary files. It goes + // to a particular offset in the file and and compares the next words + // against a given list of 'magic' tokens. + + // These checks MUST be done (even if !checkSig) if the file extension + // is not exclusive to your format. For example, .xml is very common + // and (co)used by many formats. + } + return false; +} + +// ------------------------------------------------------------------------------- +// Get list of file extensions handled by this loader +void xxxxImporter::GetExtensionList(std::set& extensions) +{ + extensions.insert("xxx"); +} + +// ------------------------------------------------------------------------------- +void xxxxImporter::InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) +{ + boost::scoped_ptr file( pIOHandler->Open( pFile, "rb")); + + // Check whether we can read from the file + if( file.get() == NULL) { + throw DeadlyImportError( "Failed to open xxxx file " + pFile + "."); + } + + // Your task: fill pScene + // Throw a ImportErrorException with a meaningful (!) error message if + // something goes wrong. +} + +@endcode + */ + + + /** + @page AnimationOverview Animation Overview + \section Transformations + This diagram shows how you can calculate your transformationmatrices for an animated character: + + + **/ diff --git a/doc/dox_cmd.h b/doc/dox_cmd.h index 8ebbcb360..bc2320e1e 100644 --- a/doc/dox_cmd.h +++ b/doc/dox_cmd.h @@ -1,548 +1,548 @@ -/** @file dox_cmd.h - * @brief General documentation for assimp_cmd - */ - - -//---------------------------------------------------------------------------------------------- -// ASSIMP CMD MAINPAGE -/** -@mainpage ASSIMP Command-line tools - - - -@section intro Introduction - -This document describes the usage of assimp's command line tools. -This is *not* the SDK reference and programming-related stuff is not covered here. -

-NOTE: For simplicity, the following sections are written with Windows in mind. However -it's not different for Linux/Mac at all, except there's probably no assimp.exe ... - -@section basic_use Basic use - -Open a command prompt and navigate to the directory where assimp.exe resides. The basic command line is: - -@code -assimp [command] [parameters] -@endcode - -The following commands are available: - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@link version version @endlinkRetrieve the current version of assimp
@link help help @endlinkGet a list of all commands (yes, it's this list ...)
@link dump dump @endlinkGenerate a human-readable text dump of a model
@link extract extract @endlinkExtract an embedded texture image
@link iinfo info @endlinkLoad a model and print basic statistics
@link cmpdump cmpdump @endlinkRegression checking tool
- -If you use assimp's command line frequently, consider adding assimp to your PATH -environment. - - */ - - -/** -@page version 'version'-Command - -Display the version/revision of Assimp used. - */ - -/** -@page help 'help'-Command - -Display a really helpful text. - */ - -//---------------------------------------------------------------------------------------------- -// ASSIMP INFO - -/** -@page iinfo 'info'-Command - -Load a model file and print basic statistics. Full postprocessing is applied unless the -r switch is specified. Sample output (assimp info ./test/models/3DS/mar_rifle.3ds): - -@verbatim -Launching model import ... OK -Validating postprocessing flags ... OK -Importing file ... OK - import took approx. 0.02400 seconds - -Memory consumption: 69444 B -Nodes: 2 -Maximum depth 2 -Meshes: 1 -Animations: 0 -Textures (embed.): 0 -Materials: 1 -Cameras: 0 -Lights: 0 -Vertices: 843 -Faces: 572 -Bones: 0 -Animation Channels: 0 -Primitive Types: triangles -Average faces/mesh 572 -Average verts/mesh 843 -Minimum point (-3.522588 -11.573204 -40.340359) -Maximum point (3.522622 30.196556 75.941292) -Center point (0.000017 9.311676 17.800467) - -Named Materials: - 'mat1' - -Texture Refs: - 'm_rifl.bmp' - -Node hierarchy: -'<3DSRoot>', meshes: 0 --- 'm_rifle', meshes: 1 -<-- -@endverbatim - -

Syntax:

- -@code -assimp info file [-r] -@endcode - - -

Parameters:

- -

- -file

-Required. Input file. -

-

- --r
-Optional. Don't perform any postprocessing. The long form of this parameter is --raw. -

- -*/ -//---------------------------------------------------------------------------------------------- -// ASSIMP CMPDUMP - -/** -@page cmpdump 'cmpdump'-Command - -Used for Assimp's internal regression testing. Compare two mini dumps (produced using assimp dump .. -b -s) and -report any differences. In the regression test suite, this facility is used to build a database of -'known-to-be-fine' mini dumps, which are regularly compared against current results to detect regressions. - -

Syntax:

- -@code -assimp cmpdmp actual expected -@endcode - - -

Parameters:

- -

- -actual

-Required. Mini dump now. -

-

- -expected

-Required. Archived dump from some point in the past. -

- -*/ - - -//---------------------------------------------------------------------------------------------- -// ASSIMP DUMP - -/** -@page dump 'dump'-Command - -Generate a text or binary dump of a model. This is the core component of Assimp's internal -regression test suite but it could also be useful for other developers to quickly -examine the contents of a model. Note that text dumps are not intended to be used as -intermediate format, Assimp is not able to read them again, nor is the file format -stable or well-defined. It may change with every revision without notice. -Binary dumps (*.assbin) are backwards- and forwards-compatible. - -

Syntax:

- -@code -assimp dump [] [-b] [-s] [common parameters] -@endcode - - -

Parameters:

- -

- -model

-Required. Relative or absolute path to the input model. -

-

- -out

-Optional. Relative or absolute path to write the output dump to. If it is omitted, -the dump is written to <model>-dump.txt -

- -

--b
-

-Optional. If this switch is specified, the dumb is written in binary format. -The long form of this parameter is --binary. -

- -

--s<n>
-

-Optional. If this switch is specified, the dumb is shortened to include only -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 -used by Assimp's regression test suite, comparing those minidumps provides -a fast way to verify whether a loader works correctly or not. -The long form of this parameter is --short. -

- -

- -common parameters

-Optional. Import configuration & postprocessing. -See the @link common common parameters page @endlink for more information. -

- -
- -

Sample:

- -@code -assimp dump test.3ds test.txt -l -cfull -assimp dump test.3ds test.txt -include-log -config=full -@endcode - -Dumps 'test.3ds' to 'test.txt' after executing full post-processing on tehe imported data. -The log output is included with the dump. - - -@code -assimp dump files\*.* -assimp dump files\*.* -@endcode - -Dumps all loadable model files in the 'files' subdir. The output dumps are named --dump.txt. The log is not included. - */ - -//---------------------------------------------------------------------------------------------- -// ASSIMP EXTRACT - -/** -@page extract 'extract'-Command - -Extracts one or more embedded texture images from models. - -

Syntax:

- -@code -assimp extract [] [-t] [-f] [-ba] [-s] [common parameters] -@endcode - - -

Parameters:

- -

- -model

-Required. Relative or absolute path to the input model. -

-

- -out

-Optional. Relative or absolute path to write the output images to. If the file name is -omitted the output images are named
-The suffix _img<n> is appended to the file name if the -s switch is not specified -(where <n> is the zero-based index of the texture in the model file).
- -The output file format is determined from the given file extension. Supported -formats are BMP and TGA. If the file format can't be determined, -the value specified with the -f switch is taken. -
-Format settings are ignored for compressed embedded textures. They're always -written in their native file format (e.g. jpg). -

- -

--t<n>
-

-Optional. Specifies the (zero-based) index of the embedded texture to be extracted from -the model. If this option is *not* specified all textures found are exported. -The long form of this parameter is --texture=<n>. -

- -

--ba<n>
-

-Optional. Specifies whether output BMPs contain an alpha channel or not. -The long form of this parameter is --bmp-with-alpha=<n>. -

- - -

--f<n>
-

-Optional. Specifies the output file format. Supported -formats are BMP and TGA. The default value is BMP (if a full output filename is -specified, the output file format is taken from its extension, not from here). -The long form of this parameter is --format=<n>. -

- -

--s<n>
-

-Optional. Prevents the tool from adding the _img<n> suffix to all filenames. This option -must be specified together with -t to ensure that just one image is written. -The long form of this parameter is --nosuffix. -

- -

- -common parameters

-Optional. Import configuration & postprocessing. Most postprocessing-steps don't affect -embedded texture images, configuring too much is probably senseless here. -See the @link common common parameters page @endlink for more information. -

- -
- -

Sample:

- -@code -assimp extract test.mdl test.bmp --texture=0 --validate-data-structure -assimp extract test.mdl test.bmp -t=0 -vds -@endcode - -Extracts the first embedded texture (if any) from test.mdl after validating the -imported data structure and writes it to test_img0.bmp. - - -@code -assimp extract files\*.mdl *.bmp -assimp extract files\*.mdl *.bmp -@endcode - -Extracts all embedded textures from all loadable .mdl files in the 'files' subdirectory -and writes them to bitmaps which are named _img.bmp - */ - -//---------------------------------------------------------------------------------------------- -// ASSIMP COMMON PARAMETERS -/** -@page common Common parameters - -The parameters described on this page are commonly used by almost every assimp command. They -specify how the library will postprocess the imported data. This is done by several -configurable pipeline stages, called 'post processing steps'. Below you can find a list -of all supported steps along with short descriptions of what they're doing.
Programmers: -more information can be found in the aiPostProcess.h header. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterLong parameterDescription
-ptv--pretransform-verticesMove all vertices into worldspace and collapse the scene graph. Animation data is lost. - This is intended for applications which don't support scenegraph-oriented rendering.
-gsn--gen-smooth-normalsComputes 'smooth' per-vertex normal vectors if necessary. Mutually exclusive with -gn
-gn--gen-normalsComputes 'hard' per-face normal vectors if necessary. Mutually exclusive with -gsn
-cts--calc-tangent-spaceIf one UV channel and normal vectors are given, compute tangents and bitangents
-jiv--join-identical-verticesOptimize the index buffer. If this flag is not specified all vertices are referenced once.
-rrm--remove-redundant-materialsRemove redundant materials from the imported data.
-fd--find-degeneratesFind and process degenerates primitives.
-slm--split-large-meshesSplit large meshes over a specific threshold in smaller sub meshes. The default vertex & face limit is 1000000
-lbw--limit-bone-weightsLimit the number of bones influencing a single vertex. The default limit is 4.
-vds--validate-data-structurePerforms a full validation of the imported data structure. Recommended to avoid crashes if - an import plugin produces rubbish
-icl--improve-cache-localityImprove the cache locality of the vertex buffer by reordering the index buffer - to achieve a lower ACMR (average post-transform vertex cache miss ratio)
-sbpt--sort-by-ptypeSplits meshes which consist of more than one kind of primitives (e.g. lines and triangles mixed up) - in 'clean' submeshes.
-lh--convert-to-lhConverts the imported data to left-handed coordinate space
-fuv--flip-uvFlip UV coordinates from upper-left origin to lower-left origin
-fwo--flip-winding-orderFlip face winding order from CCW to CW
-ett--evaluate-texture-transformEvaluate per-texture UV transformations (e.g scaling, offset) and build pretransformed UV channels
-guv--gen-uvcoordsReplace abstract mapping descriptions, such as 'spherical' or 'cylindrical' with proper UV channels
-fixn--fix-normalsRun a heuristic algorithm to detect meshes with wrong face winding order/normals.
-tri--triangulateTriangulate poylgons with 4 and more points. Lines, points and triangles are not affected.
-fi--find-instancesSearch the data structure for instanced meshes and replace them by references. This can - reduce vertex/face counts but the postprocessing-step takes some time.
-og--optimize-graphSimplify and optimize the scenegraph. Use it with care, all hierarchy information could be lost. - Animations remain untouched.
-om--optimize-meshOptimize mesh usage. Meshes are merged, if possible. Very effective in combination with --optimize-graph
- -For convenience some default postprocessing configurations are provided. -The corresponding command line parameter is -c<name> (or --config=<name>). - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionList of steps executed
fastFast post processing config, performs some essential optimizations and computes tangents-cts, -gn, -jiv, -tri, -guv, -sbpt
defaultBalanced post processing config; performs most optimizations-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv
fullFull post processing. May take a while but results in best output quality for most purposes-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv, -fi, -vds -om
- - The -tuv, -ptv, -og flags always need to be enabled manually. - -There are also some common flags to customize Assimp's logging behaviour: - - - - - - - - - - - - - - - - - - - -
NameDescription
-l or --show-logShow log file on console window (stderr)
-lo<file> or --log-out=<file>Streams the log to <file>
-v or --verboseEnables verbose logging. Debug messages will be produced too. This might - decrease loading performance and result in *very* long logs ... use with caution if you experience strange issues.
- */ +/** @file dox_cmd.h + * @brief General documentation for assimp_cmd + */ + + +//---------------------------------------------------------------------------------------------- +// ASSIMP CMD MAINPAGE +/** +@mainpage ASSIMP Command-line tools + + + +@section intro Introduction + +This document describes the usage of assimp's command line tools. +This is *not* the SDK reference and programming-related stuff is not covered here. +

+NOTE: For simplicity, the following sections are written with Windows in mind. However +it's not different for Linux/Mac at all, except there's probably no assimp.exe ... + +@section basic_use Basic use + +Open a command prompt and navigate to the directory where assimp.exe resides. The basic command line is: + +@code +assimp [command] [parameters] +@endcode + +The following commands are available: + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@link version version @endlinkRetrieve the current version of assimp
@link help help @endlinkGet a list of all commands (yes, it's this list ...)
@link dump dump @endlinkGenerate a human-readable text dump of a model
@link extract extract @endlinkExtract an embedded texture image
@link iinfo info @endlinkLoad a model and print basic statistics
@link cmpdump cmpdump @endlinkRegression checking tool
+ +If you use assimp's command line frequently, consider adding assimp to your PATH +environment. + + */ + + +/** +@page version 'version'-Command + +Display the version/revision of Assimp used. + */ + +/** +@page help 'help'-Command + +Display a really helpful text. + */ + +//---------------------------------------------------------------------------------------------- +// ASSIMP INFO + +/** +@page iinfo 'info'-Command + +Load a model file and print basic statistics. Full postprocessing is applied unless the -r switch is specified. Sample output (assimp info ./test/models/3DS/mar_rifle.3ds): + +@verbatim +Launching model import ... OK +Validating postprocessing flags ... OK +Importing file ... OK + import took approx. 0.02400 seconds + +Memory consumption: 69444 B +Nodes: 2 +Maximum depth 2 +Meshes: 1 +Animations: 0 +Textures (embed.): 0 +Materials: 1 +Cameras: 0 +Lights: 0 +Vertices: 843 +Faces: 572 +Bones: 0 +Animation Channels: 0 +Primitive Types: triangles +Average faces/mesh 572 +Average verts/mesh 843 +Minimum point (-3.522588 -11.573204 -40.340359) +Maximum point (3.522622 30.196556 75.941292) +Center point (0.000017 9.311676 17.800467) + +Named Materials: + 'mat1' + +Texture Refs: + 'm_rifl.bmp' + +Node hierarchy: +'<3DSRoot>', meshes: 0 +-- 'm_rifle', meshes: 1 +<-- +@endverbatim + +

Syntax:

+ +@code +assimp info file [-r] +@endcode + + +

Parameters:

+ +

+ +file

+Required. Input file. +

+

+ +-r
+Optional. Don't perform any postprocessing. The long form of this parameter is --raw. +

+ +*/ +//---------------------------------------------------------------------------------------------- +// ASSIMP CMPDUMP + +/** +@page cmpdump 'cmpdump'-Command + +Used for Assimp's internal regression testing. Compare two mini dumps (produced using assimp dump .. -b -s) and +report any differences. In the regression test suite, this facility is used to build a database of +'known-to-be-fine' mini dumps, which are regularly compared against current results to detect regressions. + +

Syntax:

+ +@code +assimp cmpdmp actual expected +@endcode + + +

Parameters:

+ +

+ +actual

+Required. Mini dump now. +

+

+ +expected

+Required. Archived dump from some point in the past. +

+ +*/ + + +//---------------------------------------------------------------------------------------------- +// ASSIMP DUMP + +/** +@page dump 'dump'-Command + +Generate a text or binary dump of a model. This is the core component of Assimp's internal +regression test suite but it could also be useful for other developers to quickly +examine the contents of a model. Note that text dumps are not intended to be used as +intermediate format, Assimp is not able to read them again, nor is the file format +stable or well-defined. It may change with every revision without notice. +Binary dumps (*.assbin) are backwards- and forwards-compatible. + +

Syntax:

+ +@code +assimp dump [] [-b] [-s] [common parameters] +@endcode + + +

Parameters:

+ +

+ +model

+Required. Relative or absolute path to the input model. +

+

+ +out

+Optional. Relative or absolute path to write the output dump to. If it is omitted, +the dump is written to <model>-dump.txt +

+ +

+-b
+

+Optional. If this switch is specified, the dumb is written in binary format. +The long form of this parameter is --binary. +

+ +

+-s<n>
+

+Optional. If this switch is specified, the dumb is shortened to include only +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 +used by Assimp's regression test suite, comparing those minidumps provides +a fast way to verify whether a loader works correctly or not. +The long form of this parameter is --short. +

+ +

+ +common parameters

+Optional. Import configuration & postprocessing. +See the @link common common parameters page @endlink for more information. +

+ +
+ +

Sample:

+ +@code +assimp dump test.3ds test.txt -l -cfull +assimp dump test.3ds test.txt -include-log -config=full +@endcode + +Dumps 'test.3ds' to 'test.txt' after executing full post-processing on tehe imported data. +The log output is included with the dump. + + +@code +assimp dump files\*.* +assimp dump files\*.* +@endcode + +Dumps all loadable model files in the 'files' subdir. The output dumps are named +-dump.txt. The log is not included. + */ + +//---------------------------------------------------------------------------------------------- +// ASSIMP EXTRACT + +/** +@page extract 'extract'-Command + +Extracts one or more embedded texture images from models. + +

Syntax:

+ +@code +assimp extract [] [-t] [-f] [-ba] [-s] [common parameters] +@endcode + + +

Parameters:

+ +

+ +model

+Required. Relative or absolute path to the input model. +

+

+ +out

+Optional. Relative or absolute path to write the output images to. If the file name is +omitted the output images are named
+The suffix _img<n> is appended to the file name if the -s switch is not specified +(where <n> is the zero-based index of the texture in the model file).
+ +The output file format is determined from the given file extension. Supported +formats are BMP and TGA. If the file format can't be determined, +the value specified with the -f switch is taken. +
+Format settings are ignored for compressed embedded textures. They're always +written in their native file format (e.g. jpg). +

+ +

+-t<n>
+

+Optional. Specifies the (zero-based) index of the embedded texture to be extracted from +the model. If this option is *not* specified all textures found are exported. +The long form of this parameter is --texture=<n>. +

+ +

+-ba<n>
+

+Optional. Specifies whether output BMPs contain an alpha channel or not. +The long form of this parameter is --bmp-with-alpha=<n>. +

+ + +

+-f<n>
+

+Optional. Specifies the output file format. Supported +formats are BMP and TGA. The default value is BMP (if a full output filename is +specified, the output file format is taken from its extension, not from here). +The long form of this parameter is --format=<n>. +

+ +

+-s<n>
+

+Optional. Prevents the tool from adding the _img<n> suffix to all filenames. This option +must be specified together with -t to ensure that just one image is written. +The long form of this parameter is --nosuffix. +

+ +

+ +common parameters

+Optional. Import configuration & postprocessing. Most postprocessing-steps don't affect +embedded texture images, configuring too much is probably senseless here. +See the @link common common parameters page @endlink for more information. +

+ +
+ +

Sample:

+ +@code +assimp extract test.mdl test.bmp --texture=0 --validate-data-structure +assimp extract test.mdl test.bmp -t=0 -vds +@endcode + +Extracts the first embedded texture (if any) from test.mdl after validating the +imported data structure and writes it to test_img0.bmp. + + +@code +assimp extract files\*.mdl *.bmp +assimp extract files\*.mdl *.bmp +@endcode + +Extracts all embedded textures from all loadable .mdl files in the 'files' subdirectory +and writes them to bitmaps which are named _img.bmp + */ + +//---------------------------------------------------------------------------------------------- +// ASSIMP COMMON PARAMETERS +/** +@page common Common parameters + +The parameters described on this page are commonly used by almost every assimp command. They +specify how the library will postprocess the imported data. This is done by several +configurable pipeline stages, called 'post processing steps'. Below you can find a list +of all supported steps along with short descriptions of what they're doing.
Programmers: +more information can be found in the aiPostProcess.h header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterLong parameterDescription
-ptv--pretransform-verticesMove all vertices into worldspace and collapse the scene graph. Animation data is lost. + This is intended for applications which don't support scenegraph-oriented rendering.
-gsn--gen-smooth-normalsComputes 'smooth' per-vertex normal vectors if necessary. Mutually exclusive with -gn
-gn--gen-normalsComputes 'hard' per-face normal vectors if necessary. Mutually exclusive with -gsn
-cts--calc-tangent-spaceIf one UV channel and normal vectors are given, compute tangents and bitangents
-jiv--join-identical-verticesOptimize the index buffer. If this flag is not specified all vertices are referenced once.
-rrm--remove-redundant-materialsRemove redundant materials from the imported data.
-fd--find-degeneratesFind and process degenerates primitives.
-slm--split-large-meshesSplit large meshes over a specific threshold in smaller sub meshes. The default vertex & face limit is 1000000
-lbw--limit-bone-weightsLimit the number of bones influencing a single vertex. The default limit is 4.
-vds--validate-data-structurePerforms a full validation of the imported data structure. Recommended to avoid crashes if + an import plugin produces rubbish
-icl--improve-cache-localityImprove the cache locality of the vertex buffer by reordering the index buffer + to achieve a lower ACMR (average post-transform vertex cache miss ratio)
-sbpt--sort-by-ptypeSplits meshes which consist of more than one kind of primitives (e.g. lines and triangles mixed up) + in 'clean' submeshes.
-lh--convert-to-lhConverts the imported data to left-handed coordinate space
-fuv--flip-uvFlip UV coordinates from upper-left origin to lower-left origin
-fwo--flip-winding-orderFlip face winding order from CCW to CW
-ett--evaluate-texture-transformEvaluate per-texture UV transformations (e.g scaling, offset) and build pretransformed UV channels
-guv--gen-uvcoordsReplace abstract mapping descriptions, such as 'spherical' or 'cylindrical' with proper UV channels
-fixn--fix-normalsRun a heuristic algorithm to detect meshes with wrong face winding order/normals.
-tri--triangulateTriangulate poylgons with 4 and more points. Lines, points and triangles are not affected.
-fi--find-instancesSearch the data structure for instanced meshes and replace them by references. This can + reduce vertex/face counts but the postprocessing-step takes some time.
-og--optimize-graphSimplify and optimize the scenegraph. Use it with care, all hierarchy information could be lost. + Animations remain untouched.
-om--optimize-meshOptimize mesh usage. Meshes are merged, if possible. Very effective in combination with --optimize-graph
+ +For convenience some default postprocessing configurations are provided. +The corresponding command line parameter is -c<name> (or --config=<name>). + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionList of steps executed
fastFast post processing config, performs some essential optimizations and computes tangents-cts, -gn, -jiv, -tri, -guv, -sbpt
defaultBalanced post processing config; performs most optimizations-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv
fullFull post processing. May take a while but results in best output quality for most purposes-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv, -fi, -vds -om
+ + The -tuv, -ptv, -og flags always need to be enabled manually. + +There are also some common flags to customize Assimp's logging behaviour: + + + + + + + + + + + + + + + + + + + +
NameDescription
-l or --show-logShow log file on console window (stderr)
-lo<file> or --log-out=<file>Streams the log to <file>
-v or --verboseEnables verbose logging. Debug messages will be produced too. This might + decrease loading performance and result in *very* long logs ... use with caution if you experience strange issues.
+ */ diff --git a/include/assimp/Compiler/poppack1.h b/include/assimp/Compiler/poppack1.h index 531707420..e033bc147 100644 --- a/include/assimp/Compiler/poppack1.h +++ b/include/assimp/Compiler/poppack1.h @@ -1,22 +1,22 @@ - -// =============================================================================== -// May be included multiple times - resets structure packing to the defaults -// for all supported compilers. Reverts the changes made by #include -// -// Currently this works on the following compilers: -// MSVC 7,8,9 -// GCC -// BORLAND (complains about 'pack state changed but not reverted', but works) -// =============================================================================== - -#ifndef AI_PUSHPACK_IS_DEFINED -# error pushpack1.h must be included after poppack1.h -#endif - -// reset packing to the original value -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) -# pragma pack( pop ) -#endif -#undef PACK_STRUCT - -#undef AI_PUSHPACK_IS_DEFINED + +// =============================================================================== +// May be included multiple times - resets structure packing to the defaults +// for all supported compilers. Reverts the changes made by #include +// +// Currently this works on the following compilers: +// MSVC 7,8,9 +// GCC +// BORLAND (complains about 'pack state changed but not reverted', but works) +// =============================================================================== + +#ifndef AI_PUSHPACK_IS_DEFINED +# error pushpack1.h must be included after poppack1.h +#endif + +// reset packing to the original value +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop ) +#endif +#undef PACK_STRUCT + +#undef AI_PUSHPACK_IS_DEFINED diff --git a/include/assimp/Compiler/pstdint.h b/include/assimp/Compiler/pstdint.h index 7d0e2bc58..5bc322fab 100644 --- a/include/assimp/Compiler/pstdint.h +++ b/include/assimp/Compiler/pstdint.h @@ -1,729 +1,729 @@ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2007 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - **************************************************************************** - * - * Version 0.1.10 - * - * The ANSI C standard committee, for the C99 standard, specified the - * inclusion of a new standard include file called stdint.h. This is - * a very useful and long desired include file which contains several - * very precise definitions for integer scalar types that is - * critically important for making portable several classes of - * applications including cryptography, hashing, variable length - * integer libraries and so on. But for most developers its likely - * useful just for programming sanity. - * - * The problem is that most compiler vendors have decided not to - * implement the C99 standard, and the next C++ language standard - * (which has a lot more mindshare these days) will be a long time in - * coming and its unknown whether or not it will include stdint.h or - * how much adoption it will have. Either way, it will be a long time - * before all compilers come with a stdint.h and it also does nothing - * for the extremely large number of compilers available today which - * do not include this file, or anything comparable to it. - * - * So that's what this file is all about. Its an attempt to build a - * single universal include file that works on as many platforms as - * possible to deliver what stdint.h is supposed to. A few things - * that should be noted about this file: - * - * 1) It is not guaranteed to be portable and/or present an identical - * interface on all platforms. The extreme variability of the - * ANSI C standard makes this an impossibility right from the - * very get go. Its really only meant to be useful for the vast - * majority of platforms that possess the capability of - * implementing usefully and precisely defined, standard sized - * integer scalars. Systems which are not intrinsically 2s - * complement may produce invalid constants. - * - * 2) There is an unavoidable use of non-reserved symbols. - * - * 3) Other standard include files are invoked. - * - * 4) This file may come in conflict with future platforms that do - * include stdint.h. The hope is that one or the other can be - * used with no real difference. - * - * 5) In the current verison, if your platform can't represent - * int32_t, int16_t and int8_t, it just dumps out with a compiler - * error. - * - * 6) 64 bit integers may or may not be defined. Test for their - * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. - * Note that this is different from the C99 specification which - * requires the existence of 64 bit support in the compiler. If - * this is not defined for your platform, yet it is capable of - * dealing with 64 bits then it is because this file has not yet - * been extended to cover all of your system's capabilities. - * - * 7) (u)intptr_t may or may not be defined. Test for its presence - * with the test: #ifdef PTRDIFF_MAX. If this is not defined - * for your platform, then it is because this file has not yet - * been extended to cover all of your system's capabilities, not - * because its optional. - * - * 8) The following might not been defined even if your platform is - * capable of defining it: - * - * WCHAR_MIN - * WCHAR_MAX - * (u)int64_t - * PTRDIFF_MIN - * PTRDIFF_MAX - * (u)intptr_t - * - * 9) The following have not been defined: - * - * WINT_MIN - * WINT_MAX - * - * 10) The criteria for defining (u)int_least(*)_t isn't clear, - * except for systems which don't have a type that precisely - * defined 8, 16, or 32 bit types (which this include file does - * not support anyways). Default definitions have been given. - * - * 11) The criteria for defining (u)int_fast(*)_t isn't something I - * would trust to any particular compiler vendor or the ANSI C - * committee. It is well known that "compatible systems" are - * commonly created that have very different performance - * characteristics from the systems they are compatible with, - * especially those whose vendors make both the compiler and the - * system. Default definitions have been given, but its strongly - * recommended that users never use these definitions for any - * reason (they do *NOT* deliver any serious guarantee of - * improved performance -- not in this file, nor any vendor's - * stdint.h). - * - * 12) The following macros: - * - * PRINTF_INTMAX_MODIFIER - * PRINTF_INT64_MODIFIER - * PRINTF_INT32_MODIFIER - * PRINTF_INT16_MODIFIER - * PRINTF_LEAST64_MODIFIER - * PRINTF_LEAST32_MODIFIER - * PRINTF_LEAST16_MODIFIER - * PRINTF_INTPTR_MODIFIER - * - * are strings which have been defined as the modifiers required - * for the "d", "u" and "x" printf formats to correctly output - * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, - * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. - * PRINTF_INTPTR_MODIFIER is not defined for some systems which - * provide their own stdint.h. PRINTF_INT64_MODIFIER is not - * defined if INT64_MAX is not defined. These are an extension - * beyond what C99 specifies must be in stdint.h. - * - * In addition, the following macros are defined: - * - * PRINTF_INTMAX_HEX_WIDTH - * PRINTF_INT64_HEX_WIDTH - * PRINTF_INT32_HEX_WIDTH - * PRINTF_INT16_HEX_WIDTH - * PRINTF_INT8_HEX_WIDTH - * PRINTF_INTMAX_DEC_WIDTH - * PRINTF_INT64_DEC_WIDTH - * PRINTF_INT32_DEC_WIDTH - * PRINTF_INT16_DEC_WIDTH - * PRINTF_INT8_DEC_WIDTH - * - * Which specifies the maximum number of characters required to - * print the number of that type in either hexadecimal or decimal. - * These are an extension beyond what C99 specifies must be in - * stdint.h. - * - * Compilers tested (all with 0 warnings at their highest respective - * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 - * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio - * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 - * - * This file should be considered a work in progress. Suggestions for - * improvements, especially those which increase coverage are strongly - * encouraged. - * - * Acknowledgements - * - * The following people have made significant contributions to the - * development and testing of this file: - * - * Chris Howie - * John Steele Scott - * Dave Thorup - * - */ - -#include -#include -#include - -/* - * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and - * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. - */ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)))) && !defined (_PSTDINT_H_INCLUDED) && !defined(_STDINT) -#include -#define _PSTDINT_H_INCLUDED -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -# endif -# ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -# endif -# ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -# endif -# ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -# endif -# ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -# endif -# ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -# endif -# ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -# endif -# ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif - -/* - * Something really weird is going on with Open Watcom. Just pull some of - * these duplicated definitions from Open Watcom's stdint.h file for now. - */ - -# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 -# if !defined (INT64_C) -# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) -# endif -# if !defined (UINT64_C) -# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) -# endif -# if !defined (INT32_C) -# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) -# endif -# if !defined (UINT32_C) -# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) -# endif -# if !defined (INT16_C) -# define INT16_C(x) (x) -# endif -# if !defined (UINT16_C) -# define UINT16_C(x) (x) -# endif -# if !defined (INT8_C) -# define INT8_C(x) (x) -# endif -# if !defined (UINT8_C) -# define UINT8_C(x) (x) -# endif -# if !defined (UINT64_MAX) -# define UINT64_MAX 18446744073709551615ULL -# endif -# if !defined (INT64_MAX) -# define INT64_MAX 9223372036854775807LL -# endif -# if !defined (UINT32_MAX) -# define UINT32_MAX 4294967295UL -# endif -# if !defined (INT32_MAX) -# define INT32_MAX 2147483647L -# endif -# if !defined (INTMAX_MAX) -# define INTMAX_MAX INT64_MAX -# endif -# if !defined (INTMAX_MIN) -# define INTMAX_MIN INT64_MIN -# endif -# endif -#endif - -#ifndef _PSTDINT_H_INCLUDED -#define _PSTDINT_H_INCLUDED - -#ifndef SIZE_MAX -# define SIZE_MAX (~(size_t)0) -#endif - -/* - * Deduce the type assignments from limits.h under the assumption that - * integer sizes in bits are powers of 2, and follow the ANSI - * definitions. - */ - -#ifndef UINT8_MAX -# define UINT8_MAX 0xff -#endif -#ifndef uint8_t -# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) - typedef unsigned char uint8_t; -# define UINT8_C(v) ((uint8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef INT8_MAX -# define INT8_MAX 0x7f -#endif -#ifndef INT8_MIN -# define INT8_MIN INT8_C(0x80) -#endif -#ifndef int8_t -# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) - typedef signed char int8_t; -# define INT8_C(v) ((int8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef UINT16_MAX -# define UINT16_MAX 0xffff -#endif -#ifndef uint16_t -#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) - typedef unsigned int uint16_t; -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -# define UINT16_C(v) ((uint16_t) (v)) -#elif (USHRT_MAX == UINT16_MAX) - typedef unsigned short uint16_t; -# define UINT16_C(v) ((uint16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT16_MAX -# define INT16_MAX 0x7fff -#endif -#ifndef INT16_MIN -# define INT16_MIN INT16_C(0x8000) -#endif -#ifndef int16_t -#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) - typedef signed int int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -#elif (SHRT_MAX == INT16_MAX) - typedef signed short int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef UINT32_MAX -# define UINT32_MAX (0xffffffffUL) -#endif -#ifndef uint32_t -#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) - typedef unsigned long uint32_t; -# define UINT32_C(v) v ## UL -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (UINT_MAX == UINT32_MAX) - typedef unsigned int uint32_t; -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -# define UINT32_C(v) v ## U -#elif (USHRT_MAX == UINT32_MAX) - typedef unsigned short uint32_t; -# define UINT32_C(v) ((unsigned short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT32_MAX -# define INT32_MAX (0x7fffffffL) -#endif -#ifndef INT32_MIN -# define INT32_MIN INT32_C(0x80000000) -#endif -#ifndef int32_t -#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) - typedef signed long int32_t; -# define INT32_C(v) v ## L -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (INT_MAX == INT32_MAX) - typedef signed int int32_t; -# define INT32_C(v) v -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#elif (SHRT_MAX == INT32_MAX) - typedef signed short int32_t; -# define INT32_C(v) ((short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -/* - * The macro stdint_int64_defined is temporarily used to record - * whether or not 64 integer support is available. It must be - * defined for any 64 integer extensions for new platforms that are - * added. - */ - -#undef stdint_int64_defined -#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) -# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# endif -#endif - -#if !defined (stdint_int64_defined) -# if defined(__GNUC__) -# define stdint_int64_defined - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) -# define stdint_int64_defined - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# define UINT64_C(v) v ## UI64 -# define INT64_C(v) v ## I64 -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "I64" -# endif -# endif -#endif - -#if !defined (LONG_LONG_MAX) && defined (INT64_C) -# define LONG_LONG_MAX INT64_C (9223372036854775807) -#endif -#ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX UINT64_C (18446744073709551615) -#endif - -#if !defined (INT64_MAX) && defined (INT64_C) -# define INT64_MAX INT64_C (9223372036854775807) -#endif -#if !defined (INT64_MIN) && defined (INT64_C) -# define INT64_MIN INT64_C (-9223372036854775808) -#endif -#if !defined (UINT64_MAX) && defined (INT64_C) -# define UINT64_MAX UINT64_C (18446744073709551615) -#endif - -/* - * Width of hexadecimal for number field. - */ - -#ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -#endif -#ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -#endif -#ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -#endif -#ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -#endif - -#ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -#endif -#ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -#endif -#ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -#endif -#ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -#endif - -/* - * Ok, lets not worry about 128 bit integers for now. Moore's law says - * we don't need to worry about that until about 2040 at which point - * we'll have bigger things to worry about. - */ - -#ifdef stdint_int64_defined - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; -# define INTMAX_MAX INT64_MAX -# define INTMAX_MIN INT64_MIN -# define UINTMAX_MAX UINT64_MAX -# define UINTMAX_C(v) UINT64_C(v) -# define INTMAX_C(v) INT64_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif -#else - typedef int32_t intmax_t; - typedef uint32_t uintmax_t; -# define INTMAX_MAX INT32_MAX -# define UINTMAX_MAX UINT32_MAX -# define UINTMAX_C(v) UINT32_C(v) -# define INTMAX_C(v) INT32_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH -# endif -#endif - -/* - * Because this file currently only supports platforms which have - * precise powers of 2 as bit sizes for the default integers, the - * least definitions are all trivial. Its possible that a future - * version of this file could have different definitions. - */ - -#ifndef stdint_least_defined - typedef int8_t int_least8_t; - typedef uint8_t uint_least8_t; - typedef int16_t int_least16_t; - typedef uint16_t uint_least16_t; - typedef int32_t int_least32_t; - typedef uint32_t uint_least32_t; -# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER -# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER -# define UINT_LEAST8_MAX UINT8_MAX -# define INT_LEAST8_MAX INT8_MAX -# define UINT_LEAST16_MAX UINT16_MAX -# define INT_LEAST16_MAX INT16_MAX -# define UINT_LEAST32_MAX UINT32_MAX -# define INT_LEAST32_MAX INT32_MAX -# define INT_LEAST8_MIN INT8_MIN -# define INT_LEAST16_MIN INT16_MIN -# define INT_LEAST32_MIN INT32_MIN -# ifdef stdint_int64_defined - typedef int64_t int_least64_t; - typedef uint64_t uint_least64_t; -# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER -# define UINT_LEAST64_MAX UINT64_MAX -# define INT_LEAST64_MAX INT64_MAX -# define INT_LEAST64_MIN INT64_MIN -# endif -#endif -#undef stdint_least_defined - -/* - * The ANSI C committee pretending to know or specify anything about - * performance is the epitome of misguided arrogance. The mandate of - * this file is to *ONLY* ever support that absolute minimum - * definition of the fast integer types, for compatibility purposes. - * No extensions, and no attempt to suggest what may or may not be a - * faster integer type will ever be made in this file. Developers are - * warned to stay away from these types when using this or any other - * stdint.h. - */ - -typedef int_least8_t int_fast8_t; -typedef uint_least8_t uint_fast8_t; -typedef int_least16_t int_fast16_t; -typedef uint_least16_t uint_fast16_t; -typedef int_least32_t int_fast32_t; -typedef uint_least32_t uint_fast32_t; -#define UINT_FAST8_MAX UINT_LEAST8_MAX -#define INT_FAST8_MAX INT_LEAST8_MAX -#define UINT_FAST16_MAX UINT_LEAST16_MAX -#define INT_FAST16_MAX INT_LEAST16_MAX -#define UINT_FAST32_MAX UINT_LEAST32_MAX -#define INT_FAST32_MAX INT_LEAST32_MAX -#define INT_FAST8_MIN INT_LEAST8_MIN -#define INT_FAST16_MIN INT_LEAST16_MIN -#define INT_FAST32_MIN INT_LEAST32_MIN -#ifdef stdint_int64_defined - typedef int_least64_t int_fast64_t; - typedef uint_least64_t uint_fast64_t; -# define UINT_FAST64_MAX UINT_LEAST64_MAX -# define INT_FAST64_MAX INT_LEAST64_MAX -# define INT_FAST64_MIN INT_LEAST64_MIN -#endif - -#undef stdint_int64_defined - -/* - * Whatever piecemeal, per compiler thing we can do about the wchar_t - * type limits. - */ - -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) -# include -# ifndef WCHAR_MIN -# define WCHAR_MIN 0 -# endif -# ifndef WCHAR_MAX -# define WCHAR_MAX ((wchar_t)-1) -# endif -#endif - -/* - * Whatever piecemeal, per compiler/platform thing we can do about the - * (u)intptr_t types and limits. - */ - -#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -#ifndef STDINT_H_UINTPTR_T_DEFINED -# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) -# define stdint_intptr_bits 64 -# elif defined (__WATCOMC__) || defined (__TURBOC__) -# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) -# define stdint_intptr_bits 16 -# else -# define stdint_intptr_bits 32 -# endif -# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) -# define stdint_intptr_bits 32 -# elif defined (__INTEL_COMPILER) -/* TODO -- what will Intel do about x86-64? */ -# endif - -# ifdef stdint_intptr_bits -# define stdint_intptr_glue3_i(a,b,c) a##b##c -# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) -# ifndef PRINTF_INTPTR_MODIFIER -# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) -# endif -# ifndef PTRDIFF_MAX -# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef PTRDIFF_MIN -# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef UINTPTR_MAX -# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MAX -# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MIN -# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef INTPTR_C -# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) -# endif -# ifndef UINTPTR_C -# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) -# endif - typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; - typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; -# else -/* TODO -- This following is likely wrong for some platforms, and does - nothing for the definition of uintptr_t. */ - typedef ptrdiff_t intptr_t; -# endif -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -/* - * Assumes sig_atomic_t is signed and we have a 2s complement machine. - */ - -#ifndef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) -#endif - -#endif - +/* A portable stdint.h + **************************************************************************** + * BSD License: + **************************************************************************** + * + * Copyright (c) 2005-2007 Paul Hsieh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + **************************************************************************** + * + * Version 0.1.10 + * + * The ANSI C standard committee, for the C99 standard, specified the + * inclusion of a new standard include file called stdint.h. This is + * a very useful and long desired include file which contains several + * very precise definitions for integer scalar types that is + * critically important for making portable several classes of + * applications including cryptography, hashing, variable length + * integer libraries and so on. But for most developers its likely + * useful just for programming sanity. + * + * The problem is that most compiler vendors have decided not to + * implement the C99 standard, and the next C++ language standard + * (which has a lot more mindshare these days) will be a long time in + * coming and its unknown whether or not it will include stdint.h or + * how much adoption it will have. Either way, it will be a long time + * before all compilers come with a stdint.h and it also does nothing + * for the extremely large number of compilers available today which + * do not include this file, or anything comparable to it. + * + * So that's what this file is all about. Its an attempt to build a + * single universal include file that works on as many platforms as + * possible to deliver what stdint.h is supposed to. A few things + * that should be noted about this file: + * + * 1) It is not guaranteed to be portable and/or present an identical + * interface on all platforms. The extreme variability of the + * ANSI C standard makes this an impossibility right from the + * very get go. Its really only meant to be useful for the vast + * majority of platforms that possess the capability of + * implementing usefully and precisely defined, standard sized + * integer scalars. Systems which are not intrinsically 2s + * complement may produce invalid constants. + * + * 2) There is an unavoidable use of non-reserved symbols. + * + * 3) Other standard include files are invoked. + * + * 4) This file may come in conflict with future platforms that do + * include stdint.h. The hope is that one or the other can be + * used with no real difference. + * + * 5) In the current verison, if your platform can't represent + * int32_t, int16_t and int8_t, it just dumps out with a compiler + * error. + * + * 6) 64 bit integers may or may not be defined. Test for their + * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. + * Note that this is different from the C99 specification which + * requires the existence of 64 bit support in the compiler. If + * this is not defined for your platform, yet it is capable of + * dealing with 64 bits then it is because this file has not yet + * been extended to cover all of your system's capabilities. + * + * 7) (u)intptr_t may or may not be defined. Test for its presence + * with the test: #ifdef PTRDIFF_MAX. If this is not defined + * for your platform, then it is because this file has not yet + * been extended to cover all of your system's capabilities, not + * because its optional. + * + * 8) The following might not been defined even if your platform is + * capable of defining it: + * + * WCHAR_MIN + * WCHAR_MAX + * (u)int64_t + * PTRDIFF_MIN + * PTRDIFF_MAX + * (u)intptr_t + * + * 9) The following have not been defined: + * + * WINT_MIN + * WINT_MAX + * + * 10) The criteria for defining (u)int_least(*)_t isn't clear, + * except for systems which don't have a type that precisely + * defined 8, 16, or 32 bit types (which this include file does + * not support anyways). Default definitions have been given. + * + * 11) The criteria for defining (u)int_fast(*)_t isn't something I + * would trust to any particular compiler vendor or the ANSI C + * committee. It is well known that "compatible systems" are + * commonly created that have very different performance + * characteristics from the systems they are compatible with, + * especially those whose vendors make both the compiler and the + * system. Default definitions have been given, but its strongly + * recommended that users never use these definitions for any + * reason (they do *NOT* deliver any serious guarantee of + * improved performance -- not in this file, nor any vendor's + * stdint.h). + * + * 12) The following macros: + * + * PRINTF_INTMAX_MODIFIER + * PRINTF_INT64_MODIFIER + * PRINTF_INT32_MODIFIER + * PRINTF_INT16_MODIFIER + * PRINTF_LEAST64_MODIFIER + * PRINTF_LEAST32_MODIFIER + * PRINTF_LEAST16_MODIFIER + * PRINTF_INTPTR_MODIFIER + * + * are strings which have been defined as the modifiers required + * for the "d", "u" and "x" printf formats to correctly output + * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, + * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. + * PRINTF_INTPTR_MODIFIER is not defined for some systems which + * provide their own stdint.h. PRINTF_INT64_MODIFIER is not + * defined if INT64_MAX is not defined. These are an extension + * beyond what C99 specifies must be in stdint.h. + * + * In addition, the following macros are defined: + * + * PRINTF_INTMAX_HEX_WIDTH + * PRINTF_INT64_HEX_WIDTH + * PRINTF_INT32_HEX_WIDTH + * PRINTF_INT16_HEX_WIDTH + * PRINTF_INT8_HEX_WIDTH + * PRINTF_INTMAX_DEC_WIDTH + * PRINTF_INT64_DEC_WIDTH + * PRINTF_INT32_DEC_WIDTH + * PRINTF_INT16_DEC_WIDTH + * PRINTF_INT8_DEC_WIDTH + * + * Which specifies the maximum number of characters required to + * print the number of that type in either hexadecimal or decimal. + * These are an extension beyond what C99 specifies must be in + * stdint.h. + * + * Compilers tested (all with 0 warnings at their highest respective + * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 + * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio + * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 + * + * This file should be considered a work in progress. Suggestions for + * improvements, especially those which increase coverage are strongly + * encouraged. + * + * Acknowledgements + * + * The following people have made significant contributions to the + * development and testing of this file: + * + * Chris Howie + * John Steele Scott + * Dave Thorup + * + */ + +#include +#include +#include + +/* + * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and + * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. + */ + +#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)))) && !defined (_PSTDINT_H_INCLUDED) && !defined(_STDINT) +#include +#define _PSTDINT_H_INCLUDED +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +# endif +# ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +# endif +# ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +# endif +# ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +# endif +# ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +# endif +# ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +# endif +# ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +# endif +# ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif + +/* + * Something really weird is going on with Open Watcom. Just pull some of + * these duplicated definitions from Open Watcom's stdint.h file for now. + */ + +# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 +# if !defined (INT64_C) +# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) +# endif +# if !defined (UINT64_C) +# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) +# endif +# if !defined (INT32_C) +# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) +# endif +# if !defined (UINT32_C) +# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) +# endif +# if !defined (INT16_C) +# define INT16_C(x) (x) +# endif +# if !defined (UINT16_C) +# define UINT16_C(x) (x) +# endif +# if !defined (INT8_C) +# define INT8_C(x) (x) +# endif +# if !defined (UINT8_C) +# define UINT8_C(x) (x) +# endif +# if !defined (UINT64_MAX) +# define UINT64_MAX 18446744073709551615ULL +# endif +# if !defined (INT64_MAX) +# define INT64_MAX 9223372036854775807LL +# endif +# if !defined (UINT32_MAX) +# define UINT32_MAX 4294967295UL +# endif +# if !defined (INT32_MAX) +# define INT32_MAX 2147483647L +# endif +# if !defined (INTMAX_MAX) +# define INTMAX_MAX INT64_MAX +# endif +# if !defined (INTMAX_MIN) +# define INTMAX_MIN INT64_MIN +# endif +# endif +#endif + +#ifndef _PSTDINT_H_INCLUDED +#define _PSTDINT_H_INCLUDED + +#ifndef SIZE_MAX +# define SIZE_MAX (~(size_t)0) +#endif + +/* + * Deduce the type assignments from limits.h under the assumption that + * integer sizes in bits are powers of 2, and follow the ANSI + * definitions. + */ + +#ifndef UINT8_MAX +# define UINT8_MAX 0xff +#endif +#ifndef uint8_t +# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) + typedef unsigned char uint8_t; +# define UINT8_C(v) ((uint8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef INT8_MAX +# define INT8_MAX 0x7f +#endif +#ifndef INT8_MIN +# define INT8_MIN INT8_C(0x80) +#endif +#ifndef int8_t +# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) + typedef signed char int8_t; +# define INT8_C(v) ((int8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef UINT16_MAX +# define UINT16_MAX 0xffff +#endif +#ifndef uint16_t +#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) + typedef unsigned int uint16_t; +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +# define UINT16_C(v) ((uint16_t) (v)) +#elif (USHRT_MAX == UINT16_MAX) + typedef unsigned short uint16_t; +# define UINT16_C(v) ((uint16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT16_MAX +# define INT16_MAX 0x7fff +#endif +#ifndef INT16_MIN +# define INT16_MIN INT16_C(0x8000) +#endif +#ifndef int16_t +#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) + typedef signed int int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +#elif (SHRT_MAX == INT16_MAX) + typedef signed short int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef UINT32_MAX +# define UINT32_MAX (0xffffffffUL) +#endif +#ifndef uint32_t +#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) + typedef unsigned long uint32_t; +# define UINT32_C(v) v ## UL +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (UINT_MAX == UINT32_MAX) + typedef unsigned int uint32_t; +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +# define UINT32_C(v) v ## U +#elif (USHRT_MAX == UINT32_MAX) + typedef unsigned short uint32_t; +# define UINT32_C(v) ((unsigned short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT32_MAX +# define INT32_MAX (0x7fffffffL) +#endif +#ifndef INT32_MIN +# define INT32_MIN INT32_C(0x80000000) +#endif +#ifndef int32_t +#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) + typedef signed long int32_t; +# define INT32_C(v) v ## L +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (INT_MAX == INT32_MAX) + typedef signed int int32_t; +# define INT32_C(v) v +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#elif (SHRT_MAX == INT32_MAX) + typedef signed short int32_t; +# define INT32_C(v) ((short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +/* + * The macro stdint_int64_defined is temporarily used to record + * whether or not 64 integer support is available. It must be + * defined for any 64 integer extensions for new platforms that are + * added. + */ + +#undef stdint_int64_defined +#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) +# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# endif +#endif + +#if !defined (stdint_int64_defined) +# if defined(__GNUC__) +# define stdint_int64_defined + __extension__ typedef long long int64_t; + __extension__ typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) +# define stdint_int64_defined + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +# define UINT64_C(v) v ## UI64 +# define INT64_C(v) v ## I64 +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "I64" +# endif +# endif +#endif + +#if !defined (LONG_LONG_MAX) && defined (INT64_C) +# define LONG_LONG_MAX INT64_C (9223372036854775807) +#endif +#ifndef ULONG_LONG_MAX +# define ULONG_LONG_MAX UINT64_C (18446744073709551615) +#endif + +#if !defined (INT64_MAX) && defined (INT64_C) +# define INT64_MAX INT64_C (9223372036854775807) +#endif +#if !defined (INT64_MIN) && defined (INT64_C) +# define INT64_MIN INT64_C (-9223372036854775808) +#endif +#if !defined (UINT64_MAX) && defined (INT64_C) +# define UINT64_MAX UINT64_C (18446744073709551615) +#endif + +/* + * Width of hexadecimal for number field. + */ + +#ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +#endif +#ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +#endif +#ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +#endif +#ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +#endif + +#ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +#endif +#ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +#endif +#ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +#endif +#ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +#endif + +/* + * Ok, lets not worry about 128 bit integers for now. Moore's law says + * we don't need to worry about that until about 2040 at which point + * we'll have bigger things to worry about. + */ + +#ifdef stdint_int64_defined + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; +# define INTMAX_MAX INT64_MAX +# define INTMAX_MIN INT64_MIN +# define UINTMAX_MAX UINT64_MAX +# define UINTMAX_C(v) UINT64_C(v) +# define INTMAX_C(v) INT64_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif +#else + typedef int32_t intmax_t; + typedef uint32_t uintmax_t; +# define INTMAX_MAX INT32_MAX +# define UINTMAX_MAX UINT32_MAX +# define UINTMAX_C(v) UINT32_C(v) +# define INTMAX_C(v) INT32_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH +# endif +#endif + +/* + * Because this file currently only supports platforms which have + * precise powers of 2 as bit sizes for the default integers, the + * least definitions are all trivial. Its possible that a future + * version of this file could have different definitions. + */ + +#ifndef stdint_least_defined + typedef int8_t int_least8_t; + typedef uint8_t uint_least8_t; + typedef int16_t int_least16_t; + typedef uint16_t uint_least16_t; + typedef int32_t int_least32_t; + typedef uint32_t uint_least32_t; +# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER +# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER +# define UINT_LEAST8_MAX UINT8_MAX +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# ifdef stdint_int64_defined + typedef int64_t int_least64_t; + typedef uint64_t uint_least64_t; +# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER +# define UINT_LEAST64_MAX UINT64_MAX +# define INT_LEAST64_MAX INT64_MAX +# define INT_LEAST64_MIN INT64_MIN +# endif +#endif +#undef stdint_least_defined + +/* + * The ANSI C committee pretending to know or specify anything about + * performance is the epitome of misguided arrogance. The mandate of + * this file is to *ONLY* ever support that absolute minimum + * definition of the fast integer types, for compatibility purposes. + * No extensions, and no attempt to suggest what may or may not be a + * faster integer type will ever be made in this file. Developers are + * warned to stay away from these types when using this or any other + * stdint.h. + */ + +typedef int_least8_t int_fast8_t; +typedef uint_least8_t uint_fast8_t; +typedef int_least16_t int_fast16_t; +typedef uint_least16_t uint_fast16_t; +typedef int_least32_t int_fast32_t; +typedef uint_least32_t uint_fast32_t; +#define UINT_FAST8_MAX UINT_LEAST8_MAX +#define INT_FAST8_MAX INT_LEAST8_MAX +#define UINT_FAST16_MAX UINT_LEAST16_MAX +#define INT_FAST16_MAX INT_LEAST16_MAX +#define UINT_FAST32_MAX UINT_LEAST32_MAX +#define INT_FAST32_MAX INT_LEAST32_MAX +#define INT_FAST8_MIN INT_LEAST8_MIN +#define INT_FAST16_MIN INT_LEAST16_MIN +#define INT_FAST32_MIN INT_LEAST32_MIN +#ifdef stdint_int64_defined + typedef int_least64_t int_fast64_t; + typedef uint_least64_t uint_fast64_t; +# define UINT_FAST64_MAX UINT_LEAST64_MAX +# define INT_FAST64_MAX INT_LEAST64_MAX +# define INT_FAST64_MIN INT_LEAST64_MIN +#endif + +#undef stdint_int64_defined + +/* + * Whatever piecemeal, per compiler thing we can do about the wchar_t + * type limits. + */ + +#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) +# include +# ifndef WCHAR_MIN +# define WCHAR_MIN 0 +# endif +# ifndef WCHAR_MAX +# define WCHAR_MAX ((wchar_t)-1) +# endif +#endif + +/* + * Whatever piecemeal, per compiler/platform thing we can do about the + * (u)intptr_t types and limits. + */ + +#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +#ifndef STDINT_H_UINTPTR_T_DEFINED +# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) +# define stdint_intptr_bits 64 +# elif defined (__WATCOMC__) || defined (__TURBOC__) +# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) +# define stdint_intptr_bits 16 +# else +# define stdint_intptr_bits 32 +# endif +# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) +# define stdint_intptr_bits 32 +# elif defined (__INTEL_COMPILER) +/* TODO -- what will Intel do about x86-64? */ +# endif + +# ifdef stdint_intptr_bits +# define stdint_intptr_glue3_i(a,b,c) a##b##c +# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) +# ifndef PRINTF_INTPTR_MODIFIER +# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) +# endif +# ifndef PTRDIFF_MAX +# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef PTRDIFF_MIN +# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef UINTPTR_MAX +# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MAX +# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MIN +# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef INTPTR_C +# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) +# endif +# ifndef UINTPTR_C +# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) +# endif + typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; + typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; +# else +/* TODO -- This following is likely wrong for some platforms, and does + nothing for the definition of uintptr_t. */ + typedef ptrdiff_t intptr_t; +# endif +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +/* + * Assumes sig_atomic_t is signed and we have a 2s complement machine. + */ + +#ifndef SIG_ATOMIC_MAX +# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) +#endif + +#endif + diff --git a/include/assimp/IOSystem.hpp b/include/assimp/IOSystem.hpp index 4b4d55fd4..321509de6 100644 --- a/include/assimp/IOSystem.hpp +++ b/include/assimp/IOSystem.hpp @@ -53,6 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "types.h" + +#include + namespace Assimp { class IOStream; @@ -102,18 +105,14 @@ public: * @param pFile Path to the file * @return true if there is a file with this path, else false. */ - virtual bool Exists( const char* pFile) const = 0; - - // ------------------------------------------------------------------- /** @brief Returns the system specific directory separator * @return System specific directory separator */ virtual char getOsSeparator() const = 0; - // ------------------------------------------------------------------- /** @brief Open a new file with a given path. * @@ -139,8 +138,6 @@ public: inline IOStream* Open(const std::string& pFile, const std::string& pMode = std::string("rb")); - - // ------------------------------------------------------------------- /** @brief Closes the given file and releases all resources * associated with it. @@ -170,10 +167,41 @@ public: */ inline bool ComparePaths (const std::string& one, const std::string& second) const; + + // ------------------------------------------------------------------- + /** @brief Pushes a new directory onto the directory stack. + * @param path Path to push onto the stack. + * @return True, when push was successful, false if path is empty. + */ + virtual bool PushDirectory( const std::string &path ); + + // ------------------------------------------------------------------- + /** @brief Returns the top directory from the stack. + * @return The directory on the top of the stack. + * Returns empty when no directory was pushed to the stack. + */ + virtual const std::string &CurrentDirectory() const; + + // ------------------------------------------------------------------- + /** @brief Returns the number of directories stored on the stack. + * @return The number of directories of the stack. + */ + virtual size_t StackSize() const; + + // ------------------------------------------------------------------- + /** @brief Pops the top directory from the stack. + * @return True, when a directory was on the stack. False if no + * directory was on the stack. + */ + virtual bool PopDirectory(); + +private: + std::vector m_pathStack; }; // ---------------------------------------------------------------------------- -AI_FORCE_INLINE IOSystem::IOSystem() +AI_FORCE_INLINE IOSystem::IOSystem() : + m_pathStack() { // empty } @@ -220,6 +248,43 @@ inline bool IOSystem::ComparePaths (const std::string& one, } // ---------------------------------------------------------------------------- +inline bool IOSystem::PushDirectory( const std::string &path ) { + if ( path.empty() ) { + return false; + } + + m_pathStack.push_back( path ); + + return true; +} + +// ---------------------------------------------------------------------------- +inline const std::string &IOSystem::CurrentDirectory() const { + if ( m_pathStack.empty() ) { + static const std::string Dummy(""); + return Dummy; + } + return m_pathStack[ m_pathStack.size()-1 ]; +} + +// ---------------------------------------------------------------------------- +inline size_t IOSystem::StackSize() const { + return m_pathStack.size(); +} + +// ---------------------------------------------------------------------------- +inline bool IOSystem::PopDirectory() { + if ( m_pathStack.empty() ) { + return false; + } + + m_pathStack.pop_back(); + + return true; +} + +// ---------------------------------------------------------------------------- + } //!ns Assimp #endif //AI_IOSYSTEM_H_INC diff --git a/include/assimp/defs.h b/include/assimp/defs.h index b0954920e..3129a027b 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -276,4 +276,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # define AI_BUILD_BIG_ENDIAN #endif + +/* To avoid running out of memory + * This can be adjusted for specific use cases + * It's NOT a total limit, just a limit for individual allocations + */ +#define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type)) + + #endif // !! INCLUDED_AI_DEFINES_H diff --git a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h index ad6940253..53aa2b844 100644 --- a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h +++ b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h @@ -1,92 +1,92 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp team -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** @file Android implementation of IOSystem using the standard C file functions. - * Aimed to ease the acces to android assets */ - -#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) -#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC -#define AI_ANDROIDJNIIOSYSTEM_H_INC - -#include "../code/DefaultIOSystem.h" -#include -#include -#include - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Android extension to DefaultIOSystem using the standard C file functions */ -class AndroidJNIIOSystem : public DefaultIOSystem -{ -public: - - /** Initialize android activity data */ - std::string mApkWorkspacePath; - AAssetManager* mApkAssetManager; - - /** Constructor. */ - AndroidJNIIOSystem(ANativeActivity* activity); - - /** Destructor. */ - ~AndroidJNIIOSystem(); - - // ------------------------------------------------------------------- - /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const; - - // ------------------------------------------------------------------- - /** Opens a file at the given path, with given mode */ - IOStream* Open( const char* strFile, const char* strMode); - - // ------------------------------------------------------------------------------------------------ - // Inits Android extractor - void AndroidActivityInit(ANativeActivity* activity); - - // ------------------------------------------------------------------------------------------------ - // Extracts android asset - bool AndroidExtractAsset(std::string name); - -}; - -} //!ns Assimp - -#endif //AI_ANDROIDJNIIOSYSTEM_H_INC -#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Android implementation of IOSystem using the standard C file functions. + * Aimed to ease the acces to android assets */ + +#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC +#define AI_ANDROIDJNIIOSYSTEM_H_INC + +#include "../code/DefaultIOSystem.h" +#include +#include +#include + +namespace Assimp { + +// --------------------------------------------------------------------------- +/** Android extension to DefaultIOSystem using the standard C file functions */ +class AndroidJNIIOSystem : public DefaultIOSystem +{ +public: + + /** Initialize android activity data */ + std::string mApkWorkspacePath; + AAssetManager* mApkAssetManager; + + /** Constructor. */ + AndroidJNIIOSystem(ANativeActivity* activity); + + /** Destructor. */ + ~AndroidJNIIOSystem(); + + // ------------------------------------------------------------------- + /** Tests for the existence of a file at the given path. */ + bool Exists( const char* pFile) const; + + // ------------------------------------------------------------------- + /** Opens a file at the given path, with given mode */ + IOStream* Open( const char* strFile, const char* strMode); + + // ------------------------------------------------------------------------------------------------ + // Inits Android extractor + void AndroidActivityInit(ANativeActivity* activity); + + // ------------------------------------------------------------------------------------------------ + // Extracts android asset + bool AndroidExtractAsset(std::string name); + +}; + +} //!ns Assimp + +#endif //AI_ANDROIDJNIIOSYSTEM_H_INC +#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) diff --git a/packaging/windows-innosetup/howto-build-setup.txt b/packaging/windows-innosetup/howto-build-setup.txt index 4b16eb4ef..d089c0cb4 100644 --- a/packaging/windows-innosetup/howto-build-setup.txt +++ b/packaging/windows-innosetup/howto-build-setup.txt @@ -1,16 +1,16 @@ - -How to build the Assimp installer using Inno Setup - - -1) Get MS VC 2008 SP1 redist packages for x86 and amd64 and copy 'em right here. - -vcredist_x86.exe -vcredist_x64.exe - -2) Get D3DCompiler_NN.dll and D3DX9_NN.dll from a) your system32 folder and b) your SysWOW64 folder. Copy all 4 here. Rename the 64 bit files to _x64.dll. NN is the D3DX version targeted by your DX SDK. If it is not 42, you need to update the Inno setup script (script.iss) as well. If you don't have a 64 bit Windows, get the DLLs from somebody else. Please don't ask google because many DLL downloads are infected. - -3) Build assimp, assimpcmd and assimpview for the 'release-dll' target and both the Win32 and x64 architectures. - -4) Get Inno Setup -5) Compile, output is written to the 'out' folder. - + +How to build the Assimp installer using Inno Setup + + +1) Get MS VC 2008 SP1 redist packages for x86 and amd64 and copy 'em right here. + +vcredist_x86.exe +vcredist_x64.exe + +2) Get D3DCompiler_NN.dll and D3DX9_NN.dll from a) your system32 folder and b) your SysWOW64 folder. Copy all 4 here. Rename the 64 bit files to _x64.dll. NN is the D3DX version targeted by your DX SDK. If it is not 42, you need to update the Inno setup script (script.iss) as well. If you don't have a 64 bit Windows, get the DLLs from somebody else. Please don't ask google because many DLL downloads are infected. + +3) Build assimp, assimpcmd and assimpview for the 'release-dll' target and both the Win32 and x64 architectures. + +4) Get Inno Setup +5) Compile, output is written to the 'out' folder. + diff --git a/packaging/windows-innosetup/readme_installer.txt b/packaging/windows-innosetup/readme_installer.txt index 397fae3dc..6ea969dc1 100644 --- a/packaging/windows-innosetup/readme_installer.txt +++ b/packaging/windows-innosetup/readme_installer.txt @@ -1,23 +1,23 @@ - ------------------------------------------------------------------------------------- -Open Asset Import Library (Assimp) SDK Installer -Release Notes ------------------------------------------------------------------------------------- - -http://assimp.sf.net - - -Troubleshooting -=============== - -1. Missing d3dx9_(some-number).dll? -Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). - -2. Application configuration not correct / missing msvcr***.dll? -Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) - -3. assimp.exe not in PATH -Add it to PATH. That's not a bug, the installer does not alter the PATH. - -4. Crashes immediately -You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. + +------------------------------------------------------------------------------------ +Open Asset Import Library (Assimp) SDK Installer +Release Notes +------------------------------------------------------------------------------------ + +http://assimp.sf.net + + +Troubleshooting +=============== + +1. Missing d3dx9_(some-number).dll? +Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). + +2. Application configuration not correct / missing msvcr***.dll? +Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) + +3. assimp.exe not in PATH +Add it to PATH. That's not a bug, the installer does not alter the PATH. + +4. Crashes immediately +You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. diff --git a/packaging/windows-innosetup/readme_installer_vieweronly.txt b/packaging/windows-innosetup/readme_installer_vieweronly.txt index c1ff3716a..bfa4f8c9e 100644 --- a/packaging/windows-innosetup/readme_installer_vieweronly.txt +++ b/packaging/windows-innosetup/readme_installer_vieweronly.txt @@ -1,32 +1,32 @@ - ------------------------------------------------------------------------------------- -Open Asset Import Library (Assimp) Viewer Installer -Release Notes ------------------------------------------------------------------------------------- - -http://assimp.sf.net - -Known Bugs & Limitations -======================== - -Viewer - -- Normals appear flipped from time to time when either of the normals-related menu items was hit. -- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. -- Several important texture file formats (such as GIF) are not supported. -- HUD is blurred on the right side. ATI/AMD hardware only. - -Troubleshooting -=============== - -1. Missing d3dx9_(number).dll? -Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). - -2. Application configuration not correct / missing msvcr***.dll? -Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) - -3. assimp.exe not in PATH -Add it to PATH. That's not a bug, the installer does not alter the PATH. - -4. Crashes immediately + +------------------------------------------------------------------------------------ +Open Asset Import Library (Assimp) Viewer Installer +Release Notes +------------------------------------------------------------------------------------ + +http://assimp.sf.net + +Known Bugs & Limitations +======================== + +Viewer + +- Normals appear flipped from time to time when either of the normals-related menu items was hit. +- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. +- Several important texture file formats (such as GIF) are not supported. +- HUD is blurred on the right side. ATI/AMD hardware only. + +Troubleshooting +=============== + +1. Missing d3dx9_(number).dll? +Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). + +2. Application configuration not correct / missing msvcr***.dll? +Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) + +3. assimp.exe not in PATH +Add it to PATH. That's not a bug, the installer does not alter the PATH. + +4. Crashes immediately You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. \ No newline at end of file diff --git a/packaging/windows-mkzip/bin_readme.txt b/packaging/windows-mkzip/bin_readme.txt index 3b185cfed..10839a3d9 100644 --- a/packaging/windows-mkzip/bin_readme.txt +++ b/packaging/windows-mkzip/bin_readme.txt @@ -1,29 +1,29 @@ - ------------------------------------------------------------------------------------- -Open Asset Import Library (Assimp) Tools/Binaries for Windows -Release Notes ------------------------------------------------------------------------------------- - - -Known Bugs & Limitations -======================== - -Viewer - -- For files more than one embedded texture, only the first is loaded. -- Normals appear flipped from time to time when either of the normals-related menu items was hit. -- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. -- Several important texture file formats (such as GIF) are not supported. -- HUD is blurred on the right side. ATI/AMD hardware only. - -Troubleshooting -=============== - -1. Missing d3dx9_42.dll? -Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). - -2. Application configuration not correct / missing msv*** DLLs? -(Re)install Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) - -3. Crashes immediately + +------------------------------------------------------------------------------------ +Open Asset Import Library (Assimp) Tools/Binaries for Windows +Release Notes +------------------------------------------------------------------------------------ + + +Known Bugs & Limitations +======================== + +Viewer + +- For files more than one embedded texture, only the first is loaded. +- Normals appear flipped from time to time when either of the normals-related menu items was hit. +- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. +- Several important texture file formats (such as GIF) are not supported. +- HUD is blurred on the right side. ATI/AMD hardware only. + +Troubleshooting +=============== + +1. Missing d3dx9_42.dll? +Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). + +2. Application configuration not correct / missing msv*** DLLs? +(Re)install Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) + +3. Crashes immediately You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. \ No newline at end of file diff --git a/port/AndroidJNI/AndroidJNIIOSystem.cpp b/port/AndroidJNI/AndroidJNIIOSystem.cpp index 4e8f19187..f9ba94cb1 100644 --- a/port/AndroidJNI/AndroidJNIIOSystem.cpp +++ b/port/AndroidJNI/AndroidJNIIOSystem.cpp @@ -1,173 +1,175 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/** @file Android extension of DefaultIOSystem using the standard C file functions */ - - -#include -#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor. -AndroidJNIIOSystem::AndroidJNIIOSystem(ANativeActivity* activity) -{ - AndroidActivityInit(activity); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -AndroidJNIIOSystem::~AndroidJNIIOSystem() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Tests for the existence of a file at the given path. -bool AndroidJNIIOSystem::Exists( const char* pFile) const -{ - AAsset* asset = AAssetManager_open(mApkAssetManager, pFile, - AASSET_MODE_UNKNOWN); - FILE* file = ::fopen( (mApkWorkspacePath + getOsSeparator() + std::string(pFile)).c_str(), "rb"); - - if (!asset && !file) - { - __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset manager can not find: %s", pFile); - return false; - } - - __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset exists"); - if (file) - ::fclose( file); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Inits Android extractor -void AndroidJNIIOSystem::AndroidActivityInit(ANativeActivity* activity) -{ - mApkWorkspacePath = activity->internalDataPath; - mApkAssetManager = activity->assetManager; -} - -// ------------------------------------------------------------------------------------------------ -// Extracts android asset -bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) -{ - std::string newPath = mApkWorkspacePath + getOsSeparator() + name; - - DefaultIOSystem io; - - // Do not extract if extracted already - if ( io.Exists(newPath.c_str()) ) { - __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset already extracted"); - return true; - } - // Open file - AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(), - AASSET_MODE_UNKNOWN); - std::string assetContent; - - if (asset != NULL) { - // Find size - off_t assetSize = AAsset_getLength(asset); - - // Prepare input buffer - assetContent.resize(assetSize); - - // Store input buffer - AAsset_read(asset, &assetContent[0], assetSize); - - // Close - AAsset_close(asset); - - // Prepare output buffer - std::ofstream assetExtracted(newPath.c_str(), - std::ios::out | std::ios::binary); - if (!assetExtracted) { - __android_log_print(ANDROID_LOG_ERROR, "assimp", - "Can not open output file"); - } - - // Write output buffer into a file - assetExtracted.write(assetContent.c_str(), strlen(assetContent.c_str())); - assetExtracted.close(); - - __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted"); - } else { - __android_log_print(ANDROID_LOG_ERROR, "assimp", "Asset not found: %s", name.c_str()); - return false; - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Open a new file with a given path. -IOStream* AndroidJNIIOSystem::Open( const char* strFile, const char* strMode) -{ - ai_assert(NULL != strFile); - ai_assert(NULL != strMode); - - std::string fullPath(mApkWorkspacePath + getOsSeparator() + std::string(strFile)); - if (Exists(strFile)) - AndroidExtractAsset(std::string(strFile)); - - FILE* file = ::fopen( fullPath.c_str(), strMode); - - if( NULL == file) - return NULL; - - __android_log_print(ANDROID_LOG_ERROR, "assimp", "AndroidIOSystem: file %s opened", fullPath.c_str()); - return new DefaultIOStream(file, fullPath); -} - -#undef PATHLIMIT -#endif // __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Android extension of DefaultIOSystem using the standard C file functions */ + + +#include +#include +#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Assimp; + +// ------------------------------------------------------------------------------------------------ +// Constructor. +AndroidJNIIOSystem::AndroidJNIIOSystem(ANativeActivity* activity) +{ + AndroidActivityInit(activity); +} + +// ------------------------------------------------------------------------------------------------ +// Destructor. +AndroidJNIIOSystem::~AndroidJNIIOSystem() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Tests for the existence of a file at the given path. +bool AndroidJNIIOSystem::Exists( const char* pFile) const +{ + AAsset* asset = AAssetManager_open(mApkAssetManager, pFile, + AASSET_MODE_UNKNOWN); + FILE* file = ::fopen( (mApkWorkspacePath + getOsSeparator() + std::string(pFile)).c_str(), "rb"); + + if (!asset && !file) + { + __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset manager can not find: %s", pFile); + return false; + } + + __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset exists"); + if (file) + ::fclose( file); + return true; +} + +// ------------------------------------------------------------------------------------------------ +// Inits Android extractor +void AndroidJNIIOSystem::AndroidActivityInit(ANativeActivity* activity) +{ + mApkWorkspacePath = activity->internalDataPath; + mApkAssetManager = activity->assetManager; +} + +// ------------------------------------------------------------------------------------------------ +// Extracts android asset +bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) +{ + std::string newPath = mApkWorkspacePath + getOsSeparator() + name; + + DefaultIOSystem io; + + // Do not extract if extracted already + if ( io.Exists(newPath.c_str()) ) { + __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset already extracted"); + return true; + } + // Open file + AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(), + AASSET_MODE_UNKNOWN); + std::vector assetContent; + + if (asset != NULL) { + // Find size + off_t assetSize = AAsset_getLength(asset); + + // Prepare input buffer + assetContent.resize(assetSize); + + // Store input buffer + AAsset_read(asset, &assetContent[0], assetSize); + + // Close + AAsset_close(asset); + + // Prepare output buffer + std::ofstream assetExtracted(newPath.c_str(), + std::ios::out | std::ios::binary); + if (!assetExtracted) { + __android_log_print(ANDROID_LOG_ERROR, "assimp", + "Can not open output file"); + } + + // Write output buffer into a file + assetExtracted.write(&assetContent[0], assetContent.size()); + assetExtracted.close(); + + __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted"); + } else { + __android_log_print(ANDROID_LOG_ERROR, "assimp", "Asset not found: %s", name.c_str()); + return false; + } + return true; +} + +// ------------------------------------------------------------------------------------------------ +// Open a new file with a given path. +IOStream* AndroidJNIIOSystem::Open( const char* strFile, const char* strMode) +{ + ai_assert(NULL != strFile); + ai_assert(NULL != strMode); + + std::string fullPath(mApkWorkspacePath + getOsSeparator() + std::string(strFile)); + if (Exists(strFile)) + AndroidExtractAsset(std::string(strFile)); + + FILE* file = ::fopen( fullPath.c_str(), strMode); + + if( NULL == file) + return NULL; + + __android_log_print(ANDROID_LOG_ERROR, "assimp", "AndroidIOSystem: file %s opened", fullPath.c_str()); + return new DefaultIOStream(file, fullPath); +} + +#undef PATHLIMIT +#endif // __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) diff --git a/port/AssimpDelphi/Readme.txt b/port/AssimpDelphi/Readme.txt index c9aed7b0f..07d6935ae 100644 --- a/port/AssimpDelphi/Readme.txt +++ b/port/AssimpDelphi/Readme.txt @@ -1,6 +1,6 @@ -This is a set of Delphi units for using the Assimp C DLL. This was created for use with Delphi 7, but should be usable as-is or with minimal modifications with later Delphi versions. - -This set of headers is enough to load and display a model with external textures. Since I'm not familiar with animated models and some of the other functionality of the assimp library, I did not convert the headers for those features. - -See http://sourceforge.net/tracker/?func=detail&aid=3212646&group_id=226462&atid=1067634 for the original patch - +This is a set of Delphi units for using the Assimp C DLL. This was created for use with Delphi 7, but should be usable as-is or with minimal modifications with later Delphi versions. + +This set of headers is enough to load and display a model with external textures. Since I'm not familiar with animated models and some of the other functionality of the assimp library, I did not convert the headers for those features. + +See http://sourceforge.net/tracker/?func=detail&aid=3212646&group_id=226462&atid=1067634 for the original patch + diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index ccfd8d2b5..07d09a568 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -20,6 +20,7 @@ additional_dirs, ext_whitelist = [],[] # populate search directories and lists of allowed file extensions # depending on the platform we're running on. if os.name=='posix': + additional_dirs.append('./') additional_dirs.append('/usr/lib/') additional_dirs.append('/usr/local/lib/') diff --git a/port/PyAssimp/scripts/3d_viewer.py b/port/PyAssimp/scripts/3d_viewer.py index cd417bd15..b6c131817 100755 --- a/port/PyAssimp/scripts/3d_viewer.py +++ b/port/PyAssimp/scripts/3d_viewer.py @@ -68,7 +68,7 @@ class PyAssimp3DViewer: pygame.init() pygame.display.set_caption(self.base_name) pygame.display.set_mode((w,h), pygame.OPENGL | pygame.DOUBLEBUF) - + glutInit() self.prepare_shaders() self.cameras = [DefaultCamera(w,h,fov)] diff --git a/samples/DevIL/include/IL/ilut_config.h b/samples/DevIL/include/IL/ilut_config.h index a05da54c1..2b3625b86 100644 --- a/samples/DevIL/include/IL/ilut_config.h +++ b/samples/DevIL/include/IL/ilut_config.h @@ -1,26 +1,26 @@ -#ifndef __ILUT_CONFIG_H__ -#define __ILUT_CONFIG_H__ - -#define IL_USE_PRAGMA_LIBS - -// Supported APIs (ILUT) - -// -// sorry just -// cant get this one to work under windows -// have disabled for the now -// -// will look at it some more later -// -// Kriss -// -#undef ILUT_USE_ALLEGRO - -#undef ILUT_USE_DIRECTX8 -//#define ILUT_USE_DIRECTX9 -//#define ILUT_USE_DIRECTX10 -#define ILUT_USE_OPENGL -//#define ILUT_USE_SDL -#define ILUT_USE_WIN32 - -#endif//__ILUT_CONFIG_H__ +#ifndef __ILUT_CONFIG_H__ +#define __ILUT_CONFIG_H__ + +#define IL_USE_PRAGMA_LIBS + +// Supported APIs (ILUT) + +// +// sorry just +// cant get this one to work under windows +// have disabled for the now +// +// will look at it some more later +// +// Kriss +// +#undef ILUT_USE_ALLEGRO + +#undef ILUT_USE_DIRECTX8 +//#define ILUT_USE_DIRECTX9 +//#define ILUT_USE_DIRECTX10 +#define ILUT_USE_OPENGL +//#define ILUT_USE_SDL +#define ILUT_USE_WIN32 + +#endif//__ILUT_CONFIG_H__ diff --git a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c index 0b83fd487..2f8c1a76a 100644 --- a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c +++ b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c @@ -1,389 +1,389 @@ -/* ---------------------------------------------------------------------------- -// Simple sample to prove that Assimp is easy to use with OpenGL. -// It takes a file name as command line parameter, loads it using standard -// settings and displays it. -// -// If you intend to _use_ this code sample in your app, do yourself a favour -// and replace immediate mode calls with VBOs ... -// -// The vc8 solution links against assimp-release-dll_win32 - be sure to -// have this configuration built. -// ---------------------------------------------------------------------------- -*/ - -#include -#include - -#ifdef __APPLE__ -#include -#else -#include -#endif - -/* assimp include files. These three are usually needed. */ -#include -#include -#include - -/* the global Assimp scene object */ -const struct aiScene* scene = NULL; -GLuint scene_list = 0; -struct aiVector3D scene_min, scene_max, scene_center; - -/* current rotation angle */ -static float angle = 0.f; - -#define aisgl_min(x,y) (xx?y:x) - -/* ---------------------------------------------------------------------------- */ -void reshape(int width, int height) -{ - const double aspectRatio = (float) width / height, fieldOfView = 45.0; - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(fieldOfView, aspectRatio, - 1.0, 1000.0); /* Znear and Zfar */ - glViewport(0, 0, width, height); -} - -/* ---------------------------------------------------------------------------- */ -void get_bounding_box_for_node (const struct aiNode* nd, - struct aiVector3D* min, - struct aiVector3D* max, - struct aiMatrix4x4* trafo -){ - struct aiMatrix4x4 prev; - unsigned int n = 0, t; - - prev = *trafo; - aiMultiplyMatrix4(trafo,&nd->mTransformation); - - for (; n < nd->mNumMeshes; ++n) { - const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; - for (t = 0; t < mesh->mNumVertices; ++t) { - - struct aiVector3D tmp = mesh->mVertices[t]; - aiTransformVecByMatrix4(&tmp,trafo); - - min->x = aisgl_min(min->x,tmp.x); - min->y = aisgl_min(min->y,tmp.y); - min->z = aisgl_min(min->z,tmp.z); - - max->x = aisgl_max(max->x,tmp.x); - max->y = aisgl_max(max->y,tmp.y); - max->z = aisgl_max(max->z,tmp.z); - } - } - - for (n = 0; n < nd->mNumChildren; ++n) { - get_bounding_box_for_node(nd->mChildren[n],min,max,trafo); - } - *trafo = prev; -} - -/* ---------------------------------------------------------------------------- */ -void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max) -{ - struct aiMatrix4x4 trafo; - aiIdentityMatrix4(&trafo); - - min->x = min->y = min->z = 1e10f; - max->x = max->y = max->z = -1e10f; - get_bounding_box_for_node(scene->mRootNode,min,max,&trafo); -} - -/* ---------------------------------------------------------------------------- */ -void color4_to_float4(const struct aiColor4D *c, float f[4]) -{ - f[0] = c->r; - f[1] = c->g; - f[2] = c->b; - f[3] = c->a; -} - -/* ---------------------------------------------------------------------------- */ -void set_float4(float f[4], float a, float b, float c, float d) -{ - f[0] = a; - f[1] = b; - f[2] = c; - f[3] = d; -} - -/* ---------------------------------------------------------------------------- */ -void apply_material(const struct aiMaterial *mtl) -{ - float c[4]; - - GLenum fill_mode; - int ret1, ret2; - struct aiColor4D diffuse; - struct aiColor4D specular; - struct aiColor4D ambient; - struct aiColor4D emission; - float shininess, strength; - int two_sided; - int wireframe; - unsigned int max; - - set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) - color4_to_float4(&diffuse, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); - - set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) - color4_to_float4(&specular, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); - - set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) - color4_to_float4(&ambient, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); - - set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) - color4_to_float4(&emission, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); - - max = 1; - ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); - if(ret1 == AI_SUCCESS) { - max = 1; - ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); - if(ret2 == AI_SUCCESS) - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); - else - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); - } - else { - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); - set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); - } - - max = 1; - if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) - fill_mode = wireframe ? GL_LINE : GL_FILL; - else - fill_mode = GL_FILL; - glPolygonMode(GL_FRONT_AND_BACK, fill_mode); - - max = 1; - if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) - glDisable(GL_CULL_FACE); - else - glEnable(GL_CULL_FACE); -} - -/* ---------------------------------------------------------------------------- */ -void recursive_render (const struct aiScene *sc, const struct aiNode* nd) -{ - unsigned int i; - unsigned int n = 0, t; - struct aiMatrix4x4 m = nd->mTransformation; - - /* update transform */ - aiTransposeMatrix4(&m); - glPushMatrix(); - glMultMatrixf((float*)&m); - - /* draw all meshes assigned to this node */ - for (; n < nd->mNumMeshes; ++n) { - const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; - - apply_material(sc->mMaterials[mesh->mMaterialIndex]); - - if(mesh->mNormals == NULL) { - glDisable(GL_LIGHTING); - } else { - glEnable(GL_LIGHTING); - } - - for (t = 0; t < mesh->mNumFaces; ++t) { - const struct aiFace* face = &mesh->mFaces[t]; - GLenum face_mode; - - switch(face->mNumIndices) { - case 1: face_mode = GL_POINTS; break; - case 2: face_mode = GL_LINES; break; - case 3: face_mode = GL_TRIANGLES; break; - default: face_mode = GL_POLYGON; break; - } - - glBegin(face_mode); - - for(i = 0; i < face->mNumIndices; i++) { - int index = face->mIndices[i]; - if(mesh->mColors[0] != NULL) - glColor4fv((GLfloat*)&mesh->mColors[0][index]); - if(mesh->mNormals != NULL) - glNormal3fv(&mesh->mNormals[index].x); - glVertex3fv(&mesh->mVertices[index].x); - } - - glEnd(); - } - - } - - /* draw all children */ - for (n = 0; n < nd->mNumChildren; ++n) { - recursive_render(sc, nd->mChildren[n]); - } - - glPopMatrix(); -} - -/* ---------------------------------------------------------------------------- */ -void do_motion (void) -{ - static GLint prev_time = 0; - static GLint prev_fps_time = 0; - static int frames = 0; - - int time = glutGet(GLUT_ELAPSED_TIME); - angle += (time-prev_time)*0.01; - prev_time = time; - - frames += 1; - if ((time - prev_fps_time) > 1000) /* update every seconds */ - { - int current_fps = frames * 1000 / (time - prev_fps_time); - printf("%d fps\n", current_fps); - frames = 0; - prev_fps_time = time; - } - - - glutPostRedisplay (); -} - -/* ---------------------------------------------------------------------------- */ -void display(void) -{ - float tmp; - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f); - - /* rotate it around the y axis */ - glRotatef(angle,0.f,1.f,0.f); - - /* scale the whole asset to fit into our view frustum */ - tmp = scene_max.x-scene_min.x; - tmp = aisgl_max(scene_max.y - scene_min.y,tmp); - tmp = aisgl_max(scene_max.z - scene_min.z,tmp); - tmp = 1.f / tmp; - glScalef(tmp, tmp, tmp); - - /* center the model */ - glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z ); - - /* if the display list has not been made yet, create a new one and - fill it with scene contents */ - if(scene_list == 0) { - scene_list = glGenLists(1); - glNewList(scene_list, GL_COMPILE); - /* now begin at the root node of the imported data and traverse - the scenegraph by multiplying subsequent local transforms - together on GL's matrix stack. */ - recursive_render(scene, scene->mRootNode); - glEndList(); - } - - glCallList(scene_list); - - glutSwapBuffers(); - - do_motion(); -} - -/* ---------------------------------------------------------------------------- */ -int loadasset (const char* path) -{ - /* we are taking one of the postprocessing presets to avoid - spelling out 20+ single postprocessing flags here. */ - scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality); - - if (scene) { - get_bounding_box(&scene_min,&scene_max); - scene_center.x = (scene_min.x + scene_max.x) / 2.0f; - scene_center.y = (scene_min.y + scene_max.y) / 2.0f; - scene_center.z = (scene_min.z + scene_max.z) / 2.0f; - return 0; - } - return 1; -} - -/* ---------------------------------------------------------------------------- */ -int main(int argc, char **argv) -{ - struct aiLogStream stream; - - glutInitWindowSize(900,600); - glutInitWindowPosition(100,100); - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); - glutInit(&argc, argv); - - glutCreateWindow("Assimp - Very simple OpenGL sample"); - glutDisplayFunc(display); - glutReshapeFunc(reshape); - - /* get a handle to the predefined STDOUT log stream and attach - it to the logging system. It remains active for all further - calls to aiImportFile(Ex) and aiApplyPostProcessing. */ - stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); - aiAttachLogStream(&stream); - - /* ... same procedure, but this stream now writes the - log messages to assimp_log.txt */ - stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); - aiAttachLogStream(&stream); - - /* the model name can be specified on the command line. If none - is specified, we try to locate one of the more expressive test - models from the repository (/models-nonbsd may be missing in - some distributions so we need a fallback from /models!). */ - if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) { - if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) { - return -1; - } - } - - glClearColor(0.1f,0.1f,0.1f,1.f); - - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); /* Uses default lighting parameters */ - - glEnable(GL_DEPTH_TEST); - - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - glEnable(GL_NORMALIZE); - - /* XXX docs say all polygons are emitted CCW, but tests show that some aren't. */ - if(getenv("MODEL_IS_BROKEN")) - glFrontFace(GL_CW); - - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - - glutGet(GLUT_ELAPSED_TIME); - glutMainLoop(); - - /* cleanup - calling 'aiReleaseImport' is important, as the library - keeps internal resources until the scene is freed again. Not - doing so can cause severe resource leaking. */ - aiReleaseImport(scene); - - /* We added a log stream to the library, it's our job to disable it - again. This will definitely release the last resources allocated - by Assimp.*/ - aiDetachAllLogStreams(); - return 0; -} - +/* ---------------------------------------------------------------------------- +// Simple sample to prove that Assimp is easy to use with OpenGL. +// It takes a file name as command line parameter, loads it using standard +// settings and displays it. +// +// If you intend to _use_ this code sample in your app, do yourself a favour +// and replace immediate mode calls with VBOs ... +// +// The vc8 solution links against assimp-release-dll_win32 - be sure to +// have this configuration built. +// ---------------------------------------------------------------------------- +*/ + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +/* assimp include files. These three are usually needed. */ +#include +#include +#include + +/* the global Assimp scene object */ +const struct aiScene* scene = NULL; +GLuint scene_list = 0; +struct aiVector3D scene_min, scene_max, scene_center; + +/* current rotation angle */ +static float angle = 0.f; + +#define aisgl_min(x,y) (xx?y:x) + +/* ---------------------------------------------------------------------------- */ +void reshape(int width, int height) +{ + const double aspectRatio = (float) width / height, fieldOfView = 45.0; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(fieldOfView, aspectRatio, + 1.0, 1000.0); /* Znear and Zfar */ + glViewport(0, 0, width, height); +} + +/* ---------------------------------------------------------------------------- */ +void get_bounding_box_for_node (const struct aiNode* nd, + struct aiVector3D* min, + struct aiVector3D* max, + struct aiMatrix4x4* trafo +){ + struct aiMatrix4x4 prev; + unsigned int n = 0, t; + + prev = *trafo; + aiMultiplyMatrix4(trafo,&nd->mTransformation); + + for (; n < nd->mNumMeshes; ++n) { + const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; + for (t = 0; t < mesh->mNumVertices; ++t) { + + struct aiVector3D tmp = mesh->mVertices[t]; + aiTransformVecByMatrix4(&tmp,trafo); + + min->x = aisgl_min(min->x,tmp.x); + min->y = aisgl_min(min->y,tmp.y); + min->z = aisgl_min(min->z,tmp.z); + + max->x = aisgl_max(max->x,tmp.x); + max->y = aisgl_max(max->y,tmp.y); + max->z = aisgl_max(max->z,tmp.z); + } + } + + for (n = 0; n < nd->mNumChildren; ++n) { + get_bounding_box_for_node(nd->mChildren[n],min,max,trafo); + } + *trafo = prev; +} + +/* ---------------------------------------------------------------------------- */ +void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max) +{ + struct aiMatrix4x4 trafo; + aiIdentityMatrix4(&trafo); + + min->x = min->y = min->z = 1e10f; + max->x = max->y = max->z = -1e10f; + get_bounding_box_for_node(scene->mRootNode,min,max,&trafo); +} + +/* ---------------------------------------------------------------------------- */ +void color4_to_float4(const struct aiColor4D *c, float f[4]) +{ + f[0] = c->r; + f[1] = c->g; + f[2] = c->b; + f[3] = c->a; +} + +/* ---------------------------------------------------------------------------- */ +void set_float4(float f[4], float a, float b, float c, float d) +{ + f[0] = a; + f[1] = b; + f[2] = c; + f[3] = d; +} + +/* ---------------------------------------------------------------------------- */ +void apply_material(const struct aiMaterial *mtl) +{ + float c[4]; + + GLenum fill_mode; + int ret1, ret2; + struct aiColor4D diffuse; + struct aiColor4D specular; + struct aiColor4D ambient; + struct aiColor4D emission; + float shininess, strength; + int two_sided; + int wireframe; + unsigned int max; + + set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) + color4_to_float4(&diffuse, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) + color4_to_float4(&specular, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + + set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) + color4_to_float4(&ambient, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) + color4_to_float4(&emission, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); + + max = 1; + ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); + if(ret1 == AI_SUCCESS) { + max = 1; + ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); + if(ret2 == AI_SUCCESS) + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); + else + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + } + else { + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); + set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + } + + max = 1; + if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) + fill_mode = wireframe ? GL_LINE : GL_FILL; + else + fill_mode = GL_FILL; + glPolygonMode(GL_FRONT_AND_BACK, fill_mode); + + max = 1; + if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); +} + +/* ---------------------------------------------------------------------------- */ +void recursive_render (const struct aiScene *sc, const struct aiNode* nd) +{ + unsigned int i; + unsigned int n = 0, t; + struct aiMatrix4x4 m = nd->mTransformation; + + /* update transform */ + aiTransposeMatrix4(&m); + glPushMatrix(); + glMultMatrixf((float*)&m); + + /* draw all meshes assigned to this node */ + for (; n < nd->mNumMeshes; ++n) { + const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; + + apply_material(sc->mMaterials[mesh->mMaterialIndex]); + + if(mesh->mNormals == NULL) { + glDisable(GL_LIGHTING); + } else { + glEnable(GL_LIGHTING); + } + + for (t = 0; t < mesh->mNumFaces; ++t) { + const struct aiFace* face = &mesh->mFaces[t]; + GLenum face_mode; + + switch(face->mNumIndices) { + case 1: face_mode = GL_POINTS; break; + case 2: face_mode = GL_LINES; break; + case 3: face_mode = GL_TRIANGLES; break; + default: face_mode = GL_POLYGON; break; + } + + glBegin(face_mode); + + for(i = 0; i < face->mNumIndices; i++) { + int index = face->mIndices[i]; + if(mesh->mColors[0] != NULL) + glColor4fv((GLfloat*)&mesh->mColors[0][index]); + if(mesh->mNormals != NULL) + glNormal3fv(&mesh->mNormals[index].x); + glVertex3fv(&mesh->mVertices[index].x); + } + + glEnd(); + } + + } + + /* draw all children */ + for (n = 0; n < nd->mNumChildren; ++n) { + recursive_render(sc, nd->mChildren[n]); + } + + glPopMatrix(); +} + +/* ---------------------------------------------------------------------------- */ +void do_motion (void) +{ + static GLint prev_time = 0; + static GLint prev_fps_time = 0; + static int frames = 0; + + int time = glutGet(GLUT_ELAPSED_TIME); + angle += (time-prev_time)*0.01; + prev_time = time; + + frames += 1; + if ((time - prev_fps_time) > 1000) /* update every seconds */ + { + int current_fps = frames * 1000 / (time - prev_fps_time); + printf("%d fps\n", current_fps); + frames = 0; + prev_fps_time = time; + } + + + glutPostRedisplay (); +} + +/* ---------------------------------------------------------------------------- */ +void display(void) +{ + float tmp; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f); + + /* rotate it around the y axis */ + glRotatef(angle,0.f,1.f,0.f); + + /* scale the whole asset to fit into our view frustum */ + tmp = scene_max.x-scene_min.x; + tmp = aisgl_max(scene_max.y - scene_min.y,tmp); + tmp = aisgl_max(scene_max.z - scene_min.z,tmp); + tmp = 1.f / tmp; + glScalef(tmp, tmp, tmp); + + /* center the model */ + glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z ); + + /* if the display list has not been made yet, create a new one and + fill it with scene contents */ + if(scene_list == 0) { + scene_list = glGenLists(1); + glNewList(scene_list, GL_COMPILE); + /* now begin at the root node of the imported data and traverse + the scenegraph by multiplying subsequent local transforms + together on GL's matrix stack. */ + recursive_render(scene, scene->mRootNode); + glEndList(); + } + + glCallList(scene_list); + + glutSwapBuffers(); + + do_motion(); +} + +/* ---------------------------------------------------------------------------- */ +int loadasset (const char* path) +{ + /* we are taking one of the postprocessing presets to avoid + spelling out 20+ single postprocessing flags here. */ + scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality); + + if (scene) { + get_bounding_box(&scene_min,&scene_max); + scene_center.x = (scene_min.x + scene_max.x) / 2.0f; + scene_center.y = (scene_min.y + scene_max.y) / 2.0f; + scene_center.z = (scene_min.z + scene_max.z) / 2.0f; + return 0; + } + return 1; +} + +/* ---------------------------------------------------------------------------- */ +int main(int argc, char **argv) +{ + struct aiLogStream stream; + + glutInitWindowSize(900,600); + glutInitWindowPosition(100,100); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + glutInit(&argc, argv); + + glutCreateWindow("Assimp - Very simple OpenGL sample"); + glutDisplayFunc(display); + glutReshapeFunc(reshape); + + /* get a handle to the predefined STDOUT log stream and attach + it to the logging system. It remains active for all further + calls to aiImportFile(Ex) and aiApplyPostProcessing. */ + stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); + aiAttachLogStream(&stream); + + /* ... same procedure, but this stream now writes the + log messages to assimp_log.txt */ + stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); + aiAttachLogStream(&stream); + + /* the model name can be specified on the command line. If none + is specified, we try to locate one of the more expressive test + models from the repository (/models-nonbsd may be missing in + some distributions so we need a fallback from /models!). */ + if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) { + if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) { + return -1; + } + } + + glClearColor(0.1f,0.1f,0.1f,1.f); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); /* Uses default lighting parameters */ + + glEnable(GL_DEPTH_TEST); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glEnable(GL_NORMALIZE); + + /* XXX docs say all polygons are emitted CCW, but tests show that some aren't. */ + if(getenv("MODEL_IS_BROKEN")) + glFrontFace(GL_CW); + + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + + glutGet(GLUT_ELAPSED_TIME); + glutMainLoop(); + + /* cleanup - calling 'aiReleaseImport' is important, as the library + keeps internal resources until the scene is freed again. Not + doing so can cause severe resource leaking. */ + aiReleaseImport(scene); + + /* We added a log stream to the library, it's our job to disable it + again. This will definitely release the last resources allocated + by Assimp.*/ + aiDetachAllLogStreams(); + return 0; +} + diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 2787fad52..bac800152 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -1,882 +1,882 @@ -// ---------------------------------------------------------------------------- -// Another Assimp OpenGL sample including texturing. -// Note that it is very basic and will only read and apply the model's diffuse -// textures (by their material ids) -// -// Don't worry about the "Couldn't load Image: ...dwarf2.jpg" Message. -// It's caused by a bad texture reference in the model file (I guess) -// -// If you intend to _use_ this code sample in your app, do yourself a favour -// and replace immediate mode calls with VBOs ... -// -// Thanks to NeHe on whose OpenGL tutorials this one's based on! :) -// http://nehe.gamedev.net/ -// ---------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -#include - -//to map image filenames to textureIds -#include -#include - - -// assimp include files. These three are usually needed. -#include "assimp/Importer.hpp" //OO version Header! -#include "assimp/postprocess.h" -#include "assimp/scene.h" -#include "assimp/DefaultLogger.hpp" -#include "assimp/LogStream.hpp" - - -// The default hard-coded path. Can be overridden by supplying a path through the command line. -static std::string modelpath = "../../test/models/OBJ/spider.obj"; - - -HGLRC hRC=NULL; // Permanent Rendering Context -HDC hDC=NULL; // Private GDI Device Context -HWND hWnd=NULL; // Holds Window Handle -HINSTANCE hInstance; // Holds The Instance Of The Application - -bool keys[256]; // Array used for Keyboard Routine; -bool active=TRUE; // Window Active Flag Set To TRUE by Default -bool fullscreen=TRUE; // full-screen Flag Set To full-screen By Default - -GLfloat xrot; -GLfloat yrot; -GLfloat zrot; - - -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc -GLboolean abortGLInit(const char*); - -const char* windowTitle = "OpenGL Framework"; - -GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; -GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; -GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f }; - - - -// the global Assimp scene object -const aiScene* scene = NULL; -GLuint scene_list = 0; -aiVector3D scene_min, scene_max, scene_center; - -// images / texture -std::map textureIdMap; // map image filenames to textureIds -GLuint* textureIds; // pointer to texture Array - -// Create an instance of the Importer class -Assimp::Importer importer; - - -void createAILogger() -{ - // Change this line to normal if you not want to analyse the import process - //Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL; - Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE; - - // Create a logger instance for Console Output - Assimp::DefaultLogger::create("",severity, aiDefaultLogStream_STDOUT); - - // Create a logger instance for File Output (found in project folder or near .exe) - Assimp::DefaultLogger::create("assimp_log.txt",severity, aiDefaultLogStream_FILE); - - // Now I am ready for logging my stuff - Assimp::DefaultLogger::get()->info("this is my info-call"); -} - -void destroyAILogger() -{ - // Kill it after the work is done - Assimp::DefaultLogger::kill(); -} - -void logInfo(std::string logString) -{ - // Will add message to File with "info" Tag - Assimp::DefaultLogger::get()->info(logString.c_str()); -} - -void logDebug(const char* logString) -{ - // Will add message to File with "debug" Tag - Assimp::DefaultLogger::get()->debug(logString); -} - - -bool Import3DFromFile( const std::string& pFile) -{ - // Check if file exists - std::ifstream fin(pFile.c_str()); - if(!fin.fail()) - { - fin.close(); - } - else - { - MessageBox(NULL, ("Couldn't open file: " + pFile).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION); - logInfo( importer.GetErrorString()); - return false; - } - - scene = importer.ReadFile( pFile, aiProcessPreset_TargetRealtime_Quality); - - // If the import failed, report it - if( !scene) - { - logInfo( importer.GetErrorString()); - return false; - } - - // Now we can access the file's contents. - logInfo("Import of scene " + pFile + " succeeded."); - - // We're done. Everything will be cleaned up by the importer destructor - return true; -} - -// Resize And Initialize The GL Window -void ReSizeGLScene(GLsizei width, GLsizei height) -{ - // Prevent A Divide By Zero By - if (height==0) - { - // Making Height Equal One - height=1; - } - - glViewport(0, 0, width, height); // Reset The Current Viewport - - glMatrixMode(GL_PROJECTION); // Select The Projection Matrix - glLoadIdentity(); // Reset The Projection Matrix - - // Calculate The Aspect Ratio Of The Window - gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); - - glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix - glLoadIdentity(); // Reset The Modelview Matrix -} - - -std::string getBasePath(const std::string& path) -{ - size_t pos = path.find_last_of("\\/"); - return (std::string::npos == pos) ? "" : path.substr(0, pos + 1); -} - -int LoadGLTextures(const aiScene* scene) -{ - ILboolean success; - - /* Before calling ilInit() version should be checked. */ - if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) - { - /// wrong DevIL version /// - std::string err_msg = "Wrong DevIL version. Old devil.dll in system32/SysWow64?"; - char* cErr_msg = (char *) err_msg.c_str(); - abortGLInit(cErr_msg); - return -1; - } - - ilInit(); /* Initialization of DevIL */ - - if (scene->HasTextures()) abortGLInit("Support for meshes with embedded textures is not implemented"); - - /* getTexture Filenames and Numb of Textures */ - for (unsigned int m=0; mmNumMaterials; m++) - { - int texIndex = 0; - aiReturn texFound = AI_SUCCESS; - - aiString path; // filename - - while (texFound == AI_SUCCESS) - { - texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path); - textureIdMap[path.data] = NULL; //fill map with textures, pointers still NULL yet - texIndex++; - } - } - - int numTextures = textureIdMap.size(); - - /* array with DevIL image IDs */ - ILuint* imageIds = NULL; - imageIds = new ILuint[numTextures]; - - /* generate DevIL Image IDs */ - ilGenImages(numTextures, imageIds); /* Generation of numTextures image names */ - - /* create and fill array with GL texture ids */ - textureIds = new GLuint[numTextures]; - glGenTextures(numTextures, textureIds); /* Texture name generation */ - - /* get iterator */ - std::map::iterator itr = textureIdMap.begin(); - - std::string basepath = getBasePath(modelpath); - for (int i=0; ir, color->g, color->b, color->a); -} - -void set_float4(float f[4], float a, float b, float c, float d) -{ - f[0] = a; - f[1] = b; - f[2] = c; - f[3] = d; -} - -void color4_to_float4(const aiColor4D *c, float f[4]) -{ - f[0] = c->r; - f[1] = c->g; - f[2] = c->b; - f[3] = c->a; -} - -void apply_material(const aiMaterial *mtl) -{ - float c[4]; - - GLenum fill_mode; - int ret1, ret2; - aiColor4D diffuse; - aiColor4D specular; - aiColor4D ambient; - aiColor4D emission; - float shininess, strength; - int two_sided; - int wireframe; - unsigned int max; // changed: to unsigned - - int texIndex = 0; - aiString texPath; //contains filename of texture - - if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath)) - { - //bind texture - unsigned int texId = *textureIdMap[texPath.data]; - glBindTexture(GL_TEXTURE_2D, texId); - } - - set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) - color4_to_float4(&diffuse, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); - - set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) - color4_to_float4(&specular, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); - - set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) - color4_to_float4(&ambient, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); - - set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) - color4_to_float4(&emission, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); - - max = 1; - ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); - max = 1; - ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); - if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS)) - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); - else { - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); - set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); - } - - max = 1; - if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) - fill_mode = wireframe ? GL_LINE : GL_FILL; - else - fill_mode = GL_FILL; - glPolygonMode(GL_FRONT_AND_BACK, fill_mode); - - max = 1; - if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) - glEnable(GL_CULL_FACE); - else - glDisable(GL_CULL_FACE); -} - - -void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float scale) -{ - unsigned int i; - unsigned int n=0, t; - aiMatrix4x4 m = nd->mTransformation; - - aiMatrix4x4 m2; - aiMatrix4x4::Scaling(aiVector3D(scale, scale, scale), m2); - m = m * m2; - - // update transform - m.Transpose(); - glPushMatrix(); - glMultMatrixf((float*)&m); - - // draw all meshes assigned to this node - for (; n < nd->mNumMeshes; ++n) - { - const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; - - apply_material(sc->mMaterials[mesh->mMaterialIndex]); - - - if(mesh->mNormals == NULL) - { - glDisable(GL_LIGHTING); - } - else - { - glEnable(GL_LIGHTING); - } - - if(mesh->mColors[0] != NULL) - { - glEnable(GL_COLOR_MATERIAL); - } - else - { - glDisable(GL_COLOR_MATERIAL); - } - - for (t = 0; t < mesh->mNumFaces; ++t) { - const struct aiFace* face = &mesh->mFaces[t]; - GLenum face_mode; - - switch(face->mNumIndices) - { - case 1: face_mode = GL_POINTS; break; - case 2: face_mode = GL_LINES; break; - case 3: face_mode = GL_TRIANGLES; break; - default: face_mode = GL_POLYGON; break; - } - - glBegin(face_mode); - - for(i = 0; i < face->mNumIndices; i++) // go through all vertices in face - { - int vertexIndex = face->mIndices[i]; // get group index for current index - if(mesh->mColors[0] != NULL) - Color4f(&mesh->mColors[0][vertexIndex]); - if(mesh->mNormals != NULL) - - if(mesh->HasTextureCoords(0)) //HasTextureCoords(texture_coordinates_set) - { - glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, 1 - mesh->mTextureCoords[0][vertexIndex].y); //mTextureCoords[channel][vertex] - } - - glNormal3fv(&mesh->mNormals[vertexIndex].x); - glVertex3fv(&mesh->mVertices[vertexIndex].x); - } - glEnd(); - } - } - - // draw all children - for (n = 0; n < nd->mNumChildren; ++n) - { - recursive_render(sc, nd->mChildren[n], scale); - } - - glPopMatrix(); -} - - -void drawAiScene(const aiScene* scene) -{ - logInfo("drawing objects"); - - recursive_render(scene, scene->mRootNode, 0.5); - -} - -int DrawGLScene() //Here's where we do all the drawing -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer - glLoadIdentity(); // Reset MV Matrix - - - glTranslatef(0.0f, -10.0f, -40.0f); // Move 40 Units And Into The Screen - - - glRotatef(xrot, 1.0f, 0.0f, 0.0f); - glRotatef(yrot, 0.0f, 1.0f, 0.0f); - glRotatef(zrot, 0.0f, 0.0f, 1.0f); - - drawAiScene(scene); - - //xrot+=0.3f; - yrot+=0.2f; - //zrot+=0.4f; - - return TRUE; // okay -} - - -void KillGLWindow() // Properly Kill The Window -{ - if (fullscreen) // Are We In Fullscreen Mode? - { - ChangeDisplaySettings(NULL, 0); // If So Switch Back To The Desktop - ShowCursor(TRUE); // Show Mouse Pointer - } - - if (hRC) // Do We Have A Rendering Context? - { - if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts? - { - MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - } - - if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? - { - MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - } - hRC = NULL; - } - - if (hDC && !ReleaseDC(hWnd, hDC)) // Are We able to Release The DC? - { - MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - hDC=NULL; - } - - if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window - { - MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - hWnd = NULL; - } - - if (!UnregisterClass("OpenGL", hInstance)) // Are We Able To Unregister Class - { - MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - hInstance = NULL; - } -} - -GLboolean abortGLInit(const char* abortMessage) -{ - KillGLWindow(); // Reset Display - MessageBox(NULL, abortMessage, "ERROR", MB_OK|MB_ICONEXCLAMATION); - return FALSE; // quit and return False -} - -BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool fullscreenflag) -{ - GLuint PixelFormat; // Hold the result after searching for a match - WNDCLASS wc; // Window Class Structure - DWORD dwExStyle; // Window Extended Style - DWORD dwStyle; // Window Style - RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values - WindowRect.left = (long)0; - WindowRect.right = (long)width; - WindowRect.top = (long)0; - WindowRect.bottom = (long)height; - - fullscreen = fullscreenflag; - - hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window - wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc handles Messages - wc.cbClsExtra = 0; // No Extra Window Data - wc.cbWndExtra = 0; // No Extra Window Data - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon - wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the default arrow - wc.hbrBackground= NULL; // No Background required for OpenGL - wc.lpszMenuName = NULL; // No Menu - wc.lpszClassName= "OpenGL"; // Class Name - - if (!RegisterClass(&wc)) - { - MessageBox(NULL, "Failed to register the window class", "ERROR", MB_OK | MB_ICONEXCLAMATION); - return FALSE; //exit and return false - } - - if (fullscreen) // attempt fullscreen mode - { - DEVMODE dmScreenSettings; // Device Mode - memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make Sure Memory's Cleared - dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size Of the devmode structure - dmScreenSettings.dmPelsWidth = width; // Selected Screen Width - dmScreenSettings.dmPelsHeight = height; // Selected Screen Height - dmScreenSettings.dmBitsPerPel = bits; // bits per pixel - dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - - // Try To Set Selected Mode and Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. - if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) - { - // If The Mode Fails, Offer Two Options. Quit Or Run In A Window. - if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) - { - fullscreen = FALSE; // Select Windowed Mode (Fullscreen = FALSE) - } - else - { - //Popup Messagebox: Closing - MessageBox(NULL, "Program will close now.", "ERROR", MB_OK|MB_ICONSTOP); - return FALSE; //exit, return false - } - } - } - - if (fullscreen) // when mode really succeeded - { - dwExStyle=WS_EX_APPWINDOW; // Window Extended Style - dwStyle=WS_POPUP; - ShowCursor(FALSE); - } - else - { - dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style - dwStyle=WS_OVERLAPPEDWINDOW; // Windows style - } - - AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requestes Size - - if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window - "OpenGL", // Class Name - title, // Window Title - WS_CLIPSIBLINGS | // Required Window Style - WS_CLIPCHILDREN | // Required Window Style - dwStyle, // Selected WIndow Style - 0, 0, // Window Position - WindowRect.right-WindowRect.left, // Calc adjusted Window Width - WindowRect.bottom-WindowRect.top, // Calc adjustes Window Height - NULL, // No Parent Window - NULL, // No Menu - hInstance, // Instance - NULL ))) // Don't pass anything To WM_CREATE - { - abortGLInit("Window Creation Error."); - return FALSE; - } - - static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be - { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - bits, // Select Our Color Depth - 0, 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // No Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 16, // 16Bit Z-Buffer (Depth Buffer) - 0, // No Stencil Buffer - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored - }; - - if (!(hDC=GetDC(hWnd))) // Did we get the Device Context? - { - abortGLInit("Can't Create A GL Device Context."); - return FALSE; - } - - if (!(PixelFormat=ChoosePixelFormat(hDC, &pfd))) // Did We Find a matching pixel Format? - { - abortGLInit("Can't Find Suitable PixelFormat"); - return FALSE; - } - - if (!SetPixelFormat(hDC, PixelFormat, &pfd)) - { - abortGLInit("Can't Set The PixelFormat"); - return FALSE; - } - - if (!(hRC=wglCreateContext(hDC))) - { - abortGLInit("Can't Create A GL Rendering Context."); - return FALSE; - } - - if (!(wglMakeCurrent(hDC,hRC))) // Try to activate the rendering context - { - abortGLInit("Can't Activate The Rendering Context"); - return FALSE; - } - - //// *** everything okay *** - - ShowWindow(hWnd, SW_SHOW); // Show The Window - SetForegroundWindow(hWnd); // Slightly Higher Prio - SetFocus(hWnd); // Sets Keyboard Focus To The Window - ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen - - if (!InitGL()) - { - abortGLInit("Initialization failed"); - return FALSE; - } - - return TRUE; -} - -LRESULT CALLBACK WndProc(HWND hWnd, // Handles for this Window - UINT uMsg, // Message for this Window - WPARAM wParam, // additional message Info - LPARAM lParam) // additional message Info -{ - switch (uMsg) // check for Window Messages - { - case WM_ACTIVATE: // Watch For Window Activate Message - { - if (!HIWORD(wParam)) // Check Minimization State - { - active=TRUE; - } - else - { - active=FALSE; - } - - return 0; // return To The Message Loop - } - - case WM_SYSCOMMAND: // Interrupt System Commands - { - switch (wParam) - { - case SC_SCREENSAVE: // Screen-saver trying to start - case SC_MONITORPOWER: // Monitor trying to enter power-safe - return 0; - } - break; - } - - case WM_CLOSE: // close message received? - { - PostQuitMessage(0); // Send WM_QUIT quit message - return 0; // Jump Back - } - - case WM_KEYDOWN: // Is a key pressed? - { - keys[wParam] = TRUE; // If so, Mark it as true - return 0; - } - - case WM_KEYUP: // Has Key Been released? - { - keys[wParam] = FALSE; // If so, Mark It As FALSE - return 0; - } - - case WM_SIZE: // Resize The OpenGL Window - { - ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord-Width, HiWord-Height - return 0; - } - } - - // Pass All unhandled Messaged To DefWindowProc - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -int WINAPI WinMain( HINSTANCE hInstance, // The instance - HINSTANCE hPrevInstance, // Previous instance - LPSTR lpCmdLine, // Command Line Parameters - int nShowCmd ) // Window Show State -{ - MSG msg; - BOOL done=FALSE; - - createAILogger(); - logInfo("App fired!"); - - // Check the command line for an override file path. - int argc; - LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); - if (argv != NULL && argc > 1) - { - std::wstring modelpathW(argv[1]); - modelpath = std::string(modelpathW.begin(), modelpathW.end()); - } - - if (!Import3DFromFile(modelpath)) return 0; - - logInfo("=============== Post Import ===================="); - - if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO) - { - fullscreen=FALSE; - } - - if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) - { - return 0; - } - - while(!done) // Game Loop - { - if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE)) - { - if (msg.message==WM_QUIT) - { - done=TRUE; - } - else - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - else - { - // Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene() - if (active) - { - if (keys[VK_ESCAPE]) - { - done=TRUE; - } - else - { - DrawGLScene(); - SwapBuffers(hDC); - } - } - - if (keys[VK_F1]) - { - keys[VK_F1]=FALSE; - KillGLWindow(); - fullscreen=!fullscreen; - if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) - { - return 0; - } - } - } - } - - // *** cleanup *** - - textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step) - - if (textureIds) - { - delete[] textureIds; - textureIds = NULL; - } - - // *** cleanup end *** - - destroyAILogger(); - KillGLWindow(); - return (msg.wParam); -} +// ---------------------------------------------------------------------------- +// Another Assimp OpenGL sample including texturing. +// Note that it is very basic and will only read and apply the model's diffuse +// textures (by their material ids) +// +// Don't worry about the "Couldn't load Image: ...dwarf2.jpg" Message. +// It's caused by a bad texture reference in the model file (I guess) +// +// If you intend to _use_ this code sample in your app, do yourself a favour +// and replace immediate mode calls with VBOs ... +// +// Thanks to NeHe on whose OpenGL tutorials this one's based on! :) +// http://nehe.gamedev.net/ +// ---------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +#include + +//to map image filenames to textureIds +#include +#include + + +// assimp include files. These three are usually needed. +#include "assimp/Importer.hpp" //OO version Header! +#include "assimp/postprocess.h" +#include "assimp/scene.h" +#include "assimp/DefaultLogger.hpp" +#include "assimp/LogStream.hpp" + + +// The default hard-coded path. Can be overridden by supplying a path through the command line. +static std::string modelpath = "../../test/models/OBJ/spider.obj"; + + +HGLRC hRC=NULL; // Permanent Rendering Context +HDC hDC=NULL; // Private GDI Device Context +HWND hWnd=NULL; // Holds Window Handle +HINSTANCE hInstance; // Holds The Instance Of The Application + +bool keys[256]; // Array used for Keyboard Routine; +bool active=TRUE; // Window Active Flag Set To TRUE by Default +bool fullscreen=TRUE; // full-screen Flag Set To full-screen By Default + +GLfloat xrot; +GLfloat yrot; +GLfloat zrot; + + +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc +GLboolean abortGLInit(const char*); + +const char* windowTitle = "OpenGL Framework"; + +GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; +GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; +GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f }; + + + +// the global Assimp scene object +const aiScene* scene = NULL; +GLuint scene_list = 0; +aiVector3D scene_min, scene_max, scene_center; + +// images / texture +std::map textureIdMap; // map image filenames to textureIds +GLuint* textureIds; // pointer to texture Array + +// Create an instance of the Importer class +Assimp::Importer importer; + + +void createAILogger() +{ + // Change this line to normal if you not want to analyse the import process + //Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL; + Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE; + + // Create a logger instance for Console Output + Assimp::DefaultLogger::create("",severity, aiDefaultLogStream_STDOUT); + + // Create a logger instance for File Output (found in project folder or near .exe) + Assimp::DefaultLogger::create("assimp_log.txt",severity, aiDefaultLogStream_FILE); + + // Now I am ready for logging my stuff + Assimp::DefaultLogger::get()->info("this is my info-call"); +} + +void destroyAILogger() +{ + // Kill it after the work is done + Assimp::DefaultLogger::kill(); +} + +void logInfo(std::string logString) +{ + // Will add message to File with "info" Tag + Assimp::DefaultLogger::get()->info(logString.c_str()); +} + +void logDebug(const char* logString) +{ + // Will add message to File with "debug" Tag + Assimp::DefaultLogger::get()->debug(logString); +} + + +bool Import3DFromFile( const std::string& pFile) +{ + // Check if file exists + std::ifstream fin(pFile.c_str()); + if(!fin.fail()) + { + fin.close(); + } + else + { + MessageBox(NULL, ("Couldn't open file: " + pFile).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION); + logInfo( importer.GetErrorString()); + return false; + } + + scene = importer.ReadFile( pFile, aiProcessPreset_TargetRealtime_Quality); + + // If the import failed, report it + if( !scene) + { + logInfo( importer.GetErrorString()); + return false; + } + + // Now we can access the file's contents. + logInfo("Import of scene " + pFile + " succeeded."); + + // We're done. Everything will be cleaned up by the importer destructor + return true; +} + +// Resize And Initialize The GL Window +void ReSizeGLScene(GLsizei width, GLsizei height) +{ + // Prevent A Divide By Zero By + if (height==0) + { + // Making Height Equal One + height=1; + } + + glViewport(0, 0, width, height); // Reset The Current Viewport + + glMatrixMode(GL_PROJECTION); // Select The Projection Matrix + glLoadIdentity(); // Reset The Projection Matrix + + // Calculate The Aspect Ratio Of The Window + gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); + + glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix + glLoadIdentity(); // Reset The Modelview Matrix +} + + +std::string getBasePath(const std::string& path) +{ + size_t pos = path.find_last_of("\\/"); + return (std::string::npos == pos) ? "" : path.substr(0, pos + 1); +} + +int LoadGLTextures(const aiScene* scene) +{ + ILboolean success; + + /* Before calling ilInit() version should be checked. */ + if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) + { + /// wrong DevIL version /// + std::string err_msg = "Wrong DevIL version. Old devil.dll in system32/SysWow64?"; + char* cErr_msg = (char *) err_msg.c_str(); + abortGLInit(cErr_msg); + return -1; + } + + ilInit(); /* Initialization of DevIL */ + + if (scene->HasTextures()) abortGLInit("Support for meshes with embedded textures is not implemented"); + + /* getTexture Filenames and Numb of Textures */ + for (unsigned int m=0; mmNumMaterials; m++) + { + int texIndex = 0; + aiReturn texFound = AI_SUCCESS; + + aiString path; // filename + + while (texFound == AI_SUCCESS) + { + texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path); + textureIdMap[path.data] = NULL; //fill map with textures, pointers still NULL yet + texIndex++; + } + } + + int numTextures = textureIdMap.size(); + + /* array with DevIL image IDs */ + ILuint* imageIds = NULL; + imageIds = new ILuint[numTextures]; + + /* generate DevIL Image IDs */ + ilGenImages(numTextures, imageIds); /* Generation of numTextures image names */ + + /* create and fill array with GL texture ids */ + textureIds = new GLuint[numTextures]; + glGenTextures(numTextures, textureIds); /* Texture name generation */ + + /* get iterator */ + std::map::iterator itr = textureIdMap.begin(); + + std::string basepath = getBasePath(modelpath); + for (int i=0; ir, color->g, color->b, color->a); +} + +void set_float4(float f[4], float a, float b, float c, float d) +{ + f[0] = a; + f[1] = b; + f[2] = c; + f[3] = d; +} + +void color4_to_float4(const aiColor4D *c, float f[4]) +{ + f[0] = c->r; + f[1] = c->g; + f[2] = c->b; + f[3] = c->a; +} + +void apply_material(const aiMaterial *mtl) +{ + float c[4]; + + GLenum fill_mode; + int ret1, ret2; + aiColor4D diffuse; + aiColor4D specular; + aiColor4D ambient; + aiColor4D emission; + float shininess, strength; + int two_sided; + int wireframe; + unsigned int max; // changed: to unsigned + + int texIndex = 0; + aiString texPath; //contains filename of texture + + if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath)) + { + //bind texture + unsigned int texId = *textureIdMap[texPath.data]; + glBindTexture(GL_TEXTURE_2D, texId); + } + + set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) + color4_to_float4(&diffuse, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) + color4_to_float4(&specular, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + + set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) + color4_to_float4(&ambient, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) + color4_to_float4(&emission, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); + + max = 1; + ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); + max = 1; + ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); + if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS)) + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); + else { + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); + set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + } + + max = 1; + if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) + fill_mode = wireframe ? GL_LINE : GL_FILL; + else + fill_mode = GL_FILL; + glPolygonMode(GL_FRONT_AND_BACK, fill_mode); + + max = 1; + if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); +} + + +void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float scale) +{ + unsigned int i; + unsigned int n=0, t; + aiMatrix4x4 m = nd->mTransformation; + + aiMatrix4x4 m2; + aiMatrix4x4::Scaling(aiVector3D(scale, scale, scale), m2); + m = m * m2; + + // update transform + m.Transpose(); + glPushMatrix(); + glMultMatrixf((float*)&m); + + // draw all meshes assigned to this node + for (; n < nd->mNumMeshes; ++n) + { + const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; + + apply_material(sc->mMaterials[mesh->mMaterialIndex]); + + + if(mesh->mNormals == NULL) + { + glDisable(GL_LIGHTING); + } + else + { + glEnable(GL_LIGHTING); + } + + if(mesh->mColors[0] != NULL) + { + glEnable(GL_COLOR_MATERIAL); + } + else + { + glDisable(GL_COLOR_MATERIAL); + } + + for (t = 0; t < mesh->mNumFaces; ++t) { + const struct aiFace* face = &mesh->mFaces[t]; + GLenum face_mode; + + switch(face->mNumIndices) + { + case 1: face_mode = GL_POINTS; break; + case 2: face_mode = GL_LINES; break; + case 3: face_mode = GL_TRIANGLES; break; + default: face_mode = GL_POLYGON; break; + } + + glBegin(face_mode); + + for(i = 0; i < face->mNumIndices; i++) // go through all vertices in face + { + int vertexIndex = face->mIndices[i]; // get group index for current index + if(mesh->mColors[0] != NULL) + Color4f(&mesh->mColors[0][vertexIndex]); + if(mesh->mNormals != NULL) + + if(mesh->HasTextureCoords(0)) //HasTextureCoords(texture_coordinates_set) + { + glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, 1 - mesh->mTextureCoords[0][vertexIndex].y); //mTextureCoords[channel][vertex] + } + + glNormal3fv(&mesh->mNormals[vertexIndex].x); + glVertex3fv(&mesh->mVertices[vertexIndex].x); + } + glEnd(); + } + } + + // draw all children + for (n = 0; n < nd->mNumChildren; ++n) + { + recursive_render(sc, nd->mChildren[n], scale); + } + + glPopMatrix(); +} + + +void drawAiScene(const aiScene* scene) +{ + logInfo("drawing objects"); + + recursive_render(scene, scene->mRootNode, 0.5); + +} + +int DrawGLScene() //Here's where we do all the drawing +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer + glLoadIdentity(); // Reset MV Matrix + + + glTranslatef(0.0f, -10.0f, -40.0f); // Move 40 Units And Into The Screen + + + glRotatef(xrot, 1.0f, 0.0f, 0.0f); + glRotatef(yrot, 0.0f, 1.0f, 0.0f); + glRotatef(zrot, 0.0f, 0.0f, 1.0f); + + drawAiScene(scene); + + //xrot+=0.3f; + yrot+=0.2f; + //zrot+=0.4f; + + return TRUE; // okay +} + + +void KillGLWindow() // Properly Kill The Window +{ + if (fullscreen) // Are We In Fullscreen Mode? + { + ChangeDisplaySettings(NULL, 0); // If So Switch Back To The Desktop + ShowCursor(TRUE); // Show Mouse Pointer + } + + if (hRC) // Do We Have A Rendering Context? + { + if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts? + { + MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + + if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? + { + MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + hRC = NULL; + } + + if (hDC && !ReleaseDC(hWnd, hDC)) // Are We able to Release The DC? + { + MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hDC=NULL; + } + + if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window + { + MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hWnd = NULL; + } + + if (!UnregisterClass("OpenGL", hInstance)) // Are We Able To Unregister Class + { + MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hInstance = NULL; + } +} + +GLboolean abortGLInit(const char* abortMessage) +{ + KillGLWindow(); // Reset Display + MessageBox(NULL, abortMessage, "ERROR", MB_OK|MB_ICONEXCLAMATION); + return FALSE; // quit and return False +} + +BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool fullscreenflag) +{ + GLuint PixelFormat; // Hold the result after searching for a match + WNDCLASS wc; // Window Class Structure + DWORD dwExStyle; // Window Extended Style + DWORD dwStyle; // Window Style + RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values + WindowRect.left = (long)0; + WindowRect.right = (long)width; + WindowRect.top = (long)0; + WindowRect.bottom = (long)height; + + fullscreen = fullscreenflag; + + hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window + wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc handles Messages + wc.cbClsExtra = 0; // No Extra Window Data + wc.cbWndExtra = 0; // No Extra Window Data + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon + wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the default arrow + wc.hbrBackground= NULL; // No Background required for OpenGL + wc.lpszMenuName = NULL; // No Menu + wc.lpszClassName= "OpenGL"; // Class Name + + if (!RegisterClass(&wc)) + { + MessageBox(NULL, "Failed to register the window class", "ERROR", MB_OK | MB_ICONEXCLAMATION); + return FALSE; //exit and return false + } + + if (fullscreen) // attempt fullscreen mode + { + DEVMODE dmScreenSettings; // Device Mode + memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make Sure Memory's Cleared + dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size Of the devmode structure + dmScreenSettings.dmPelsWidth = width; // Selected Screen Width + dmScreenSettings.dmPelsHeight = height; // Selected Screen Height + dmScreenSettings.dmBitsPerPel = bits; // bits per pixel + dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + // Try To Set Selected Mode and Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) + { + // If The Mode Fails, Offer Two Options. Quit Or Run In A Window. + if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) + { + fullscreen = FALSE; // Select Windowed Mode (Fullscreen = FALSE) + } + else + { + //Popup Messagebox: Closing + MessageBox(NULL, "Program will close now.", "ERROR", MB_OK|MB_ICONSTOP); + return FALSE; //exit, return false + } + } + } + + if (fullscreen) // when mode really succeeded + { + dwExStyle=WS_EX_APPWINDOW; // Window Extended Style + dwStyle=WS_POPUP; + ShowCursor(FALSE); + } + else + { + dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style + dwStyle=WS_OVERLAPPEDWINDOW; // Windows style + } + + AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requestes Size + + if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window + "OpenGL", // Class Name + title, // Window Title + WS_CLIPSIBLINGS | // Required Window Style + WS_CLIPCHILDREN | // Required Window Style + dwStyle, // Selected WIndow Style + 0, 0, // Window Position + WindowRect.right-WindowRect.left, // Calc adjusted Window Width + WindowRect.bottom-WindowRect.top, // Calc adjustes Window Height + NULL, // No Parent Window + NULL, // No Menu + hInstance, // Instance + NULL ))) // Don't pass anything To WM_CREATE + { + abortGLInit("Window Creation Error."); + return FALSE; + } + + static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be + { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_TYPE_RGBA, // Request An RGBA Format + bits, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // No Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 16, // 16Bit Z-Buffer (Depth Buffer) + 0, // No Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + if (!(hDC=GetDC(hWnd))) // Did we get the Device Context? + { + abortGLInit("Can't Create A GL Device Context."); + return FALSE; + } + + if (!(PixelFormat=ChoosePixelFormat(hDC, &pfd))) // Did We Find a matching pixel Format? + { + abortGLInit("Can't Find Suitable PixelFormat"); + return FALSE; + } + + if (!SetPixelFormat(hDC, PixelFormat, &pfd)) + { + abortGLInit("Can't Set The PixelFormat"); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))) + { + abortGLInit("Can't Create A GL Rendering Context."); + return FALSE; + } + + if (!(wglMakeCurrent(hDC,hRC))) // Try to activate the rendering context + { + abortGLInit("Can't Activate The Rendering Context"); + return FALSE; + } + + //// *** everything okay *** + + ShowWindow(hWnd, SW_SHOW); // Show The Window + SetForegroundWindow(hWnd); // Slightly Higher Prio + SetFocus(hWnd); // Sets Keyboard Focus To The Window + ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen + + if (!InitGL()) + { + abortGLInit("Initialization failed"); + return FALSE; + } + + return TRUE; +} + +LRESULT CALLBACK WndProc(HWND hWnd, // Handles for this Window + UINT uMsg, // Message for this Window + WPARAM wParam, // additional message Info + LPARAM lParam) // additional message Info +{ + switch (uMsg) // check for Window Messages + { + case WM_ACTIVATE: // Watch For Window Activate Message + { + if (!HIWORD(wParam)) // Check Minimization State + { + active=TRUE; + } + else + { + active=FALSE; + } + + return 0; // return To The Message Loop + } + + case WM_SYSCOMMAND: // Interrupt System Commands + { + switch (wParam) + { + case SC_SCREENSAVE: // Screen-saver trying to start + case SC_MONITORPOWER: // Monitor trying to enter power-safe + return 0; + } + break; + } + + case WM_CLOSE: // close message received? + { + PostQuitMessage(0); // Send WM_QUIT quit message + return 0; // Jump Back + } + + case WM_KEYDOWN: // Is a key pressed? + { + keys[wParam] = TRUE; // If so, Mark it as true + return 0; + } + + case WM_KEYUP: // Has Key Been released? + { + keys[wParam] = FALSE; // If so, Mark It As FALSE + return 0; + } + + case WM_SIZE: // Resize The OpenGL Window + { + ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord-Width, HiWord-Height + return 0; + } + } + + // Pass All unhandled Messaged To DefWindowProc + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +int WINAPI WinMain( HINSTANCE hInstance, // The instance + HINSTANCE hPrevInstance, // Previous instance + LPSTR lpCmdLine, // Command Line Parameters + int nShowCmd ) // Window Show State +{ + MSG msg; + BOOL done=FALSE; + + createAILogger(); + logInfo("App fired!"); + + // Check the command line for an override file path. + int argc; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); + if (argv != NULL && argc > 1) + { + std::wstring modelpathW(argv[1]); + modelpath = std::string(modelpathW.begin(), modelpathW.end()); + } + + if (!Import3DFromFile(modelpath)) return 0; + + logInfo("=============== Post Import ===================="); + + if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO) + { + fullscreen=FALSE; + } + + if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) + { + return 0; + } + + while(!done) // Game Loop + { + if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE)) + { + if (msg.message==WM_QUIT) + { + done=TRUE; + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else + { + // Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene() + if (active) + { + if (keys[VK_ESCAPE]) + { + done=TRUE; + } + else + { + DrawGLScene(); + SwapBuffers(hDC); + } + } + + if (keys[VK_F1]) + { + keys[VK_F1]=FALSE; + KillGLWindow(); + fullscreen=!fullscreen; + if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) + { + return 0; + } + } + } + } + + // *** cleanup *** + + textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step) + + if (textureIds) + { + delete[] textureIds; + textureIds = NULL; + } + + // *** cleanup end *** + + destroyAILogger(); + KillGLWindow(); + return (msg.wParam); +} diff --git a/samples/glut/GL/glut.h b/samples/glut/GL/glut.h index aa7428f36..0e6ddfbfe 100644 --- a/samples/glut/GL/glut.h +++ b/samples/glut/GL/glut.h @@ -1,716 +1,716 @@ -#ifndef __glut_h__ -#define __glut_h__ - -/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ - -/* This program is freely distributable without licensing fees and is - provided without guarantee or warrantee expressed or implied. This - program is -not- in the public domain. */ - -#if defined(_WIN32) - -/* GLUT 3.7 now tries to avoid including - to avoid name space pollution, but Win32's - needs APIENTRY and WINGDIAPI defined properly. */ -# if 0 - /* This would put tons of macros and crap in our clean name space. */ -# define WIN32_LEAN_AND_MEAN -# include -# else - /* XXX This is from Win32's */ -# ifndef APIENTRY -# define GLUT_APIENTRY_DEFINED -# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) || defined(__LCC__) -# define APIENTRY __stdcall -# else -# define APIENTRY -# endif -# endif - /* XXX This is from Win32's */ -# ifndef CALLBACK -# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) || defined(__LCC__) -# define CALLBACK __stdcall -# else -# define CALLBACK -# endif -# endif - /* XXX Hack for lcc compiler. It doesn't support __declspec(dllimport), just __stdcall. */ -# if defined( __LCC__ ) -# undef WINGDIAPI -# define WINGDIAPI __stdcall -# else - /* XXX This is from Win32's and */ -# ifndef WINGDIAPI -# define GLUT_WINGDIAPI_DEFINED -# define WINGDIAPI __declspec(dllimport) -# endif -# endif - /* XXX This is from Win32's */ -# ifndef _WCHAR_T_DEFINED -typedef unsigned short wchar_t; -# define _WCHAR_T_DEFINED -# endif -# endif - -/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA - in your compile preprocessor options. */ -# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) -# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ -/* To enable automatic SGI OpenGL for Windows library usage for GLUT, - define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ -# ifdef GLUT_USE_SGI_OPENGL -# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ -# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ -# pragma comment (lib, "glut.lib") /* link with Win32 GLUT for SGI OpenGL lib */ -# else -# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ -# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ -# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ -# endif -# endif - -/* To disable supression of annoying warnings about floats being promoted - to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor - options. */ -# ifndef GLUT_NO_WARNING_DISABLE -# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ -# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ -# endif - -/* Win32 has an annoying issue where there are multiple C run-time - libraries (CRTs). If the executable is linked with a different CRT - from the GLUT DLL, the GLUT DLL will not share the same CRT static - data seen by the executable. In particular, atexit callbacks registered - in the executable will not be called if GLUT calls its (different) - exit routine). GLUT is typically built with the - "/MD" option (the CRT with multithreading DLL support), but the Visual - C++ linker default is "/ML" (the single threaded CRT). - - One workaround to this issue is requiring users to always link with - the same CRT as GLUT is compiled with. That requires users supply a - non-standard option. GLUT 3.7 has its own built-in workaround where - the executable's "exit" function pointer is covertly passed to GLUT. - GLUT then calls the executable's exit function pointer to ensure that - any "atexit" calls registered by the application are called if GLUT - needs to exit. - - Note that the __glut*WithExit routines should NEVER be called directly. - To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ - -/* XXX This is from Win32's */ -# if !defined(_MSC_VER) && !defined(__cdecl) - /* Define __cdecl for non-Microsoft compilers. */ -# define __cdecl -# define GLUT_DEFINED___CDECL -# endif -# ifndef _CRTIMP -# ifdef _NTSDK - /* Definition compatible with NT SDK */ -# define _CRTIMP -# else - /* Current definition */ -# ifdef _DLL -# define _CRTIMP __declspec(dllimport) -# else -# define _CRTIMP -# endif -# endif -# define GLUT_DEFINED__CRTIMP -# endif - -/* GLUT API entry point declarations for Win32. */ -# ifdef GLUT_BUILDING_LIB -# define GLUTAPI __declspec(dllexport) -# else -# ifdef _DLL -# define GLUTAPI __declspec(dllimport) -# else -# define GLUTAPI extern -# endif -# endif - -/* GLUT callback calling convention for Win32. */ -# define GLUTCALLBACK __cdecl - -#endif /* _WIN32 */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(_WIN32) -# ifndef GLUT_BUILDING_LIB -extern _CRTIMP void __cdecl exit(int); -# endif -#else -/* non-Win32 case. */ -/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */ -# define APIENTRY -# define GLUT_APIENTRY_DEFINED -# define CALLBACK -/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */ -# define GLUTAPI extern -# define GLUTCALLBACK -/* Prototype exit for the non-Win32 case (see above). */ -extern void exit(int); -#endif - -/** - GLUT API revision history: - - GLUT_API_VERSION is updated to reflect incompatible GLUT - API changes (interface changes, semantic changes, deletions, - or additions). - - GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 - - GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, - extension. Supports new input devices like tablet, dial and button - box, and Spaceball. Easy to query OpenGL extensions. - - GLUT_API_VERSION=3 glutMenuStatus added. - - GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, - glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic - video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, - glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, - glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). -**/ -#ifndef GLUT_API_VERSION /* allow this to be overriden */ -#define GLUT_API_VERSION 3 -#endif - -/** - GLUT implementation revision history: - - GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT - API revisions and implementation revisions (ie, bug fixes). - - GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of - GLUT Xlib-based implementation. 11/29/94 - - GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of - GLUT Xlib-based implementation providing GLUT version 2 - interfaces. - - GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 - - GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 - - GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 - - GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 - - GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner - and video resize. 1/3/97 - - GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. - - GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. - - GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. - - GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. - - GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. - - GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa -**/ -#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ -#define GLUT_XLIB_IMPLEMENTATION 15 -#endif - -/* Display mode bit masks. */ -#define GLUT_RGB 0 -#define GLUT_RGBA GLUT_RGB -#define GLUT_INDEX 1 -#define GLUT_SINGLE 0 -#define GLUT_DOUBLE 2 -#define GLUT_ACCUM 4 -#define GLUT_ALPHA 8 -#define GLUT_DEPTH 16 -#define GLUT_STENCIL 32 -#if (GLUT_API_VERSION >= 2) -#define GLUT_MULTISAMPLE 128 -#define GLUT_STEREO 256 -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_LUMINANCE 512 -#endif - -/* Mouse buttons. */ -#define GLUT_LEFT_BUTTON 0 -#define GLUT_MIDDLE_BUTTON 1 -#define GLUT_RIGHT_BUTTON 2 - -/* Mouse button state. */ -#define GLUT_DOWN 0 -#define GLUT_UP 1 - -#if (GLUT_API_VERSION >= 2) -/* function keys */ -#define GLUT_KEY_F1 1 -#define GLUT_KEY_F2 2 -#define GLUT_KEY_F3 3 -#define GLUT_KEY_F4 4 -#define GLUT_KEY_F5 5 -#define GLUT_KEY_F6 6 -#define GLUT_KEY_F7 7 -#define GLUT_KEY_F8 8 -#define GLUT_KEY_F9 9 -#define GLUT_KEY_F10 10 -#define GLUT_KEY_F11 11 -#define GLUT_KEY_F12 12 -/* directional keys */ -#define GLUT_KEY_LEFT 100 -#define GLUT_KEY_UP 101 -#define GLUT_KEY_RIGHT 102 -#define GLUT_KEY_DOWN 103 -#define GLUT_KEY_PAGE_UP 104 -#define GLUT_KEY_PAGE_DOWN 105 -#define GLUT_KEY_HOME 106 -#define GLUT_KEY_END 107 -#define GLUT_KEY_INSERT 108 -#endif - -/* Entry/exit state. */ -#define GLUT_LEFT 0 -#define GLUT_ENTERED 1 - -/* Menu usage state. */ -#define GLUT_MENU_NOT_IN_USE 0 -#define GLUT_MENU_IN_USE 1 - -/* Visibility state. */ -#define GLUT_NOT_VISIBLE 0 -#define GLUT_VISIBLE 1 - -/* Window status state. */ -#define GLUT_HIDDEN 0 -#define GLUT_FULLY_RETAINED 1 -#define GLUT_PARTIALLY_RETAINED 2 -#define GLUT_FULLY_COVERED 3 - -/* Color index component selection values. */ -#define GLUT_RED 0 -#define GLUT_GREEN 1 -#define GLUT_BLUE 2 - -#if defined(_WIN32) -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN ((void*)0) -#define GLUT_STROKE_MONO_ROMAN ((void*)1) - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 ((void*)2) -#define GLUT_BITMAP_8_BY_13 ((void*)3) -#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) -#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 ((void*)6) -#define GLUT_BITMAP_HELVETICA_12 ((void*)7) -#define GLUT_BITMAP_HELVETICA_18 ((void*)8) -#endif -#else -/* Stroke font opaque addresses (use constants instead in source code). */ -GLUTAPI void *glutStrokeRoman; -GLUTAPI void *glutStrokeMonoRoman; - -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN (&glutStrokeRoman) -#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) - -/* Bitmap font opaque addresses (use constants instead in source code). */ -GLUTAPI void *glutBitmap9By15; -GLUTAPI void *glutBitmap8By13; -GLUTAPI void *glutBitmapTimesRoman10; -GLUTAPI void *glutBitmapTimesRoman24; -GLUTAPI void *glutBitmapHelvetica10; -GLUTAPI void *glutBitmapHelvetica12; -GLUTAPI void *glutBitmapHelvetica18; - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) -#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) -#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) -#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) -#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) -#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) -#endif -#endif - -/* glutGet parameters. */ -#define GLUT_WINDOW_X ((GLenum) 100) -#define GLUT_WINDOW_Y ((GLenum) 101) -#define GLUT_WINDOW_WIDTH ((GLenum) 102) -#define GLUT_WINDOW_HEIGHT ((GLenum) 103) -#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104) -#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105) -#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106) -#define GLUT_WINDOW_RED_SIZE ((GLenum) 107) -#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108) -#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109) -#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110) -#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111) -#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112) -#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113) -#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114) -#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115) -#define GLUT_WINDOW_RGBA ((GLenum) 116) -#define GLUT_WINDOW_PARENT ((GLenum) 117) -#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118) -#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119) -#if (GLUT_API_VERSION >= 2) -#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120) -#define GLUT_WINDOW_STEREO ((GLenum) 121) -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_WINDOW_CURSOR ((GLenum) 122) -#endif -#define GLUT_SCREEN_WIDTH ((GLenum) 200) -#define GLUT_SCREEN_HEIGHT ((GLenum) 201) -#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202) -#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203) -#define GLUT_MENU_NUM_ITEMS ((GLenum) 300) -#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400) -#define GLUT_INIT_WINDOW_X ((GLenum) 500) -#define GLUT_INIT_WINDOW_Y ((GLenum) 501) -#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502) -#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503) -#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504) -#if (GLUT_API_VERSION >= 2) -#define GLUT_ELAPSED_TIME ((GLenum) 700) -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123) -#endif - -#if (GLUT_API_VERSION >= 2) -/* glutDeviceGet parameters. */ -#define GLUT_HAS_KEYBOARD ((GLenum) 600) -#define GLUT_HAS_MOUSE ((GLenum) 601) -#define GLUT_HAS_SPACEBALL ((GLenum) 602) -#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603) -#define GLUT_HAS_TABLET ((GLenum) 604) -#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605) -#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606) -#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607) -#define GLUT_NUM_DIALS ((GLenum) 608) -#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609) -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610) -#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611) -#define GLUT_HAS_JOYSTICK ((GLenum) 612) -#define GLUT_OWNS_JOYSTICK ((GLenum) 613) -#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614) -#define GLUT_JOYSTICK_AXES ((GLenum) 615) -#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616) -#endif - -#if (GLUT_API_VERSION >= 3) -/* glutLayerGet parameters. */ -#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800) -#define GLUT_LAYER_IN_USE ((GLenum) 801) -#define GLUT_HAS_OVERLAY ((GLenum) 802) -#define GLUT_TRANSPARENT_INDEX ((GLenum) 803) -#define GLUT_NORMAL_DAMAGED ((GLenum) 804) -#define GLUT_OVERLAY_DAMAGED ((GLenum) 805) - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* glutVideoResizeGet parameters. */ -#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900) -#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901) -#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902) -#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903) -#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904) -#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905) -#define GLUT_VIDEO_RESIZE_X ((GLenum) 906) -#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907) -#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908) -#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909) -#endif - -/* glutUseLayer parameters. */ -#define GLUT_NORMAL ((GLenum) 0) -#define GLUT_OVERLAY ((GLenum) 1) - -/* glutGetModifiers return mask. */ -#define GLUT_ACTIVE_SHIFT 1 -#define GLUT_ACTIVE_CTRL 2 -#define GLUT_ACTIVE_ALT 4 - -/* glutSetCursor parameters. */ -/* Basic arrows. */ -#define GLUT_CURSOR_RIGHT_ARROW 0 -#define GLUT_CURSOR_LEFT_ARROW 1 -/* Symbolic cursor shapes. */ -#define GLUT_CURSOR_INFO 2 -#define GLUT_CURSOR_DESTROY 3 -#define GLUT_CURSOR_HELP 4 -#define GLUT_CURSOR_CYCLE 5 -#define GLUT_CURSOR_SPRAY 6 -#define GLUT_CURSOR_WAIT 7 -#define GLUT_CURSOR_TEXT 8 -#define GLUT_CURSOR_CROSSHAIR 9 -/* Directional cursors. */ -#define GLUT_CURSOR_UP_DOWN 10 -#define GLUT_CURSOR_LEFT_RIGHT 11 -/* Sizing cursors. */ -#define GLUT_CURSOR_TOP_SIDE 12 -#define GLUT_CURSOR_BOTTOM_SIDE 13 -#define GLUT_CURSOR_LEFT_SIDE 14 -#define GLUT_CURSOR_RIGHT_SIDE 15 -#define GLUT_CURSOR_TOP_LEFT_CORNER 16 -#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 -#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 -#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 -/* Inherit from parent window. */ -#define GLUT_CURSOR_INHERIT 100 -/* Blank cursor. */ -#define GLUT_CURSOR_NONE 101 -/* Fullscreen crosshair (if available). */ -#define GLUT_CURSOR_FULL_CROSSHAIR 102 -#endif - -/* GLUT initialization sub-API. */ -GLUTAPI void APIENTRY glutInit(int *argcp, char **argv); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } -#define glutInit glutInit_ATEXIT_HACK -#endif -#endif -GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutInitDisplayString(const char *string); -#endif -GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y); -GLUTAPI void APIENTRY glutInitWindowSize(int width, int height); -GLUTAPI void APIENTRY glutMainLoop(void); - -/* GLUT window sub-API. */ -GLUTAPI int APIENTRY glutCreateWindow(const char *title); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } -#define glutCreateWindow glutCreateWindow_ATEXIT_HACK -#endif -#endif -GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); -GLUTAPI void APIENTRY glutDestroyWindow(int win); -GLUTAPI void APIENTRY glutPostRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -GLUTAPI void APIENTRY glutPostWindowRedisplay(int win); -#endif -GLUTAPI void APIENTRY glutSwapBuffers(void); -GLUTAPI int APIENTRY glutGetWindow(void); -GLUTAPI void APIENTRY glutSetWindow(int win); -GLUTAPI void APIENTRY glutSetWindowTitle(const char *title); -GLUTAPI void APIENTRY glutSetIconTitle(const char *title); -GLUTAPI void APIENTRY glutPositionWindow(int x, int y); -GLUTAPI void APIENTRY glutReshapeWindow(int width, int height); -GLUTAPI void APIENTRY glutPopWindow(void); -GLUTAPI void APIENTRY glutPushWindow(void); -GLUTAPI void APIENTRY glutIconifyWindow(void); -GLUTAPI void APIENTRY glutShowWindow(void); -GLUTAPI void APIENTRY glutHideWindow(void); -#if (GLUT_API_VERSION >= 3) -GLUTAPI void APIENTRY glutFullScreen(void); -GLUTAPI void APIENTRY glutSetCursor(int cursor); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutWarpPointer(int x, int y); -#endif - -/* GLUT overlay sub-API. */ -GLUTAPI void APIENTRY glutEstablishOverlay(void); -GLUTAPI void APIENTRY glutRemoveOverlay(void); -GLUTAPI void APIENTRY glutUseLayer(GLenum layer); -GLUTAPI void APIENTRY glutPostOverlayRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win); -#endif -GLUTAPI void APIENTRY glutShowOverlay(void); -GLUTAPI void APIENTRY glutHideOverlay(void); -#endif - -/* GLUT menu sub-API. */ -GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } -#define glutCreateMenu glutCreateMenu_ATEXIT_HACK -#endif -#endif -GLUTAPI void APIENTRY glutDestroyMenu(int menu); -GLUTAPI int APIENTRY glutGetMenu(void); -GLUTAPI void APIENTRY glutSetMenu(int menu); -GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value); -GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu); -GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); -GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); -GLUTAPI void APIENTRY glutRemoveMenuItem(int item); -GLUTAPI void APIENTRY glutAttachMenu(int button); -GLUTAPI void APIENTRY glutDetachMenu(int button); - -/* GLUT window callback sub-API. */ -GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); -GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); -GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); -GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); -GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); -GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); -GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); -GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); -GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); -#if (GLUT_API_VERSION >= 2) -GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); -GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); -GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); -GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); -GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); -#if (GLUT_API_VERSION >= 3) -GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); -GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); -GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); -GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); -#endif -#endif -#endif - -/* GLUT color index sub-API. */ -GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); -GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component); -GLUTAPI void APIENTRY glutCopyColormap(int win); - -/* GLUT state retrieval sub-API. */ -GLUTAPI int APIENTRY glutGet(GLenum type); -GLUTAPI int APIENTRY glutDeviceGet(GLenum type); -#if (GLUT_API_VERSION >= 2) -/* GLUT extension support sub-API */ -GLUTAPI int APIENTRY glutExtensionSupported(const char *name); -#endif -#if (GLUT_API_VERSION >= 3) -GLUTAPI int APIENTRY glutGetModifiers(void); -GLUTAPI int APIENTRY glutLayerGet(GLenum type); -#endif - -/* GLUT font sub-API */ -GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character); -GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character); -GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character); -GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string); -GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string); -#endif - -/* GLUT pre-built models sub-API */ -GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCube(GLdouble size); -GLUTAPI void APIENTRY glutSolidCube(GLdouble size); -GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutWireDodecahedron(void); -GLUTAPI void APIENTRY glutSolidDodecahedron(void); -GLUTAPI void APIENTRY glutWireTeapot(GLdouble size); -GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size); -GLUTAPI void APIENTRY glutWireOctahedron(void); -GLUTAPI void APIENTRY glutSolidOctahedron(void); -GLUTAPI void APIENTRY glutWireTetrahedron(void); -GLUTAPI void APIENTRY glutSolidTetrahedron(void); -GLUTAPI void APIENTRY glutWireIcosahedron(void); -GLUTAPI void APIENTRY glutSolidIcosahedron(void); - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* GLUT video resize sub-API. */ -GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param); -GLUTAPI void APIENTRY glutSetupVideoResizing(void); -GLUTAPI void APIENTRY glutStopVideoResizing(void); -GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height); -GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height); - -/* GLUT debugging sub-API. */ -GLUTAPI void APIENTRY glutReportErrors(void); -#endif - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -/* GLUT device control sub-API. */ -/* glutSetKeyRepeat modes. */ -#define GLUT_KEY_REPEAT_OFF 0 -#define GLUT_KEY_REPEAT_ON 1 -#define GLUT_KEY_REPEAT_DEFAULT 2 - -/* Joystick button masks. */ -#define GLUT_JOYSTICK_BUTTON_A 1 -#define GLUT_JOYSTICK_BUTTON_B 2 -#define GLUT_JOYSTICK_BUTTON_C 4 -#define GLUT_JOYSTICK_BUTTON_D 8 - -GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore); -GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode); -GLUTAPI void APIENTRY glutForceJoystickFunc(void); - -/* GLUT game mode sub-API. */ -/* glutGameModeGet. */ -#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0) -#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1) -#define GLUT_GAME_MODE_WIDTH ((GLenum) 2) -#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3) -#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4) -#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5) -#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6) - -GLUTAPI void APIENTRY glutGameModeString(const char *string); -GLUTAPI int APIENTRY glutEnterGameMode(void); -GLUTAPI void APIENTRY glutLeaveGameMode(void); -GLUTAPI int APIENTRY glutGameModeGet(GLenum mode); -#endif - -#ifdef __cplusplus -} - -#endif - -#ifdef GLUT_APIENTRY_DEFINED -# undef GLUT_APIENTRY_DEFINED -# undef APIENTRY -#endif - -#ifdef GLUT_WINGDIAPI_DEFINED -# undef GLUT_WINGDIAPI_DEFINED -# undef WINGDIAPI -#endif - -#ifdef GLUT_DEFINED___CDECL -# undef GLUT_DEFINED___CDECL -# undef __cdecl -#endif - -#ifdef GLUT_DEFINED__CRTIMP -# undef GLUT_DEFINED__CRTIMP -# undef _CRTIMP -#endif - -#endif /* __glut_h__ */ +#ifndef __glut_h__ +#define __glut_h__ + +/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ + +/* This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. */ + +#if defined(_WIN32) + +/* GLUT 3.7 now tries to avoid including + to avoid name space pollution, but Win32's + needs APIENTRY and WINGDIAPI defined properly. */ +# if 0 + /* This would put tons of macros and crap in our clean name space. */ +# define WIN32_LEAN_AND_MEAN +# include +# else + /* XXX This is from Win32's */ +# ifndef APIENTRY +# define GLUT_APIENTRY_DEFINED +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) || defined(__LCC__) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +# endif + /* XXX This is from Win32's */ +# ifndef CALLBACK +# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) || defined(__LCC__) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +# endif + /* XXX Hack for lcc compiler. It doesn't support __declspec(dllimport), just __stdcall. */ +# if defined( __LCC__ ) +# undef WINGDIAPI +# define WINGDIAPI __stdcall +# else + /* XXX This is from Win32's and */ +# ifndef WINGDIAPI +# define GLUT_WINGDIAPI_DEFINED +# define WINGDIAPI __declspec(dllimport) +# endif +# endif + /* XXX This is from Win32's */ +# ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +# endif +# endif + +/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA + in your compile preprocessor options. */ +# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) +# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ +/* To enable automatic SGI OpenGL for Windows library usage for GLUT, + define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ +# ifdef GLUT_USE_SGI_OPENGL +# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ +# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ +# pragma comment (lib, "glut.lib") /* link with Win32 GLUT for SGI OpenGL lib */ +# else +# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ +# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ +# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ +# endif +# endif + +/* To disable supression of annoying warnings about floats being promoted + to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor + options. */ +# ifndef GLUT_NO_WARNING_DISABLE +# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ +# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ +# endif + +/* Win32 has an annoying issue where there are multiple C run-time + libraries (CRTs). If the executable is linked with a different CRT + from the GLUT DLL, the GLUT DLL will not share the same CRT static + data seen by the executable. In particular, atexit callbacks registered + in the executable will not be called if GLUT calls its (different) + exit routine). GLUT is typically built with the + "/MD" option (the CRT with multithreading DLL support), but the Visual + C++ linker default is "/ML" (the single threaded CRT). + + One workaround to this issue is requiring users to always link with + the same CRT as GLUT is compiled with. That requires users supply a + non-standard option. GLUT 3.7 has its own built-in workaround where + the executable's "exit" function pointer is covertly passed to GLUT. + GLUT then calls the executable's exit function pointer to ensure that + any "atexit" calls registered by the application are called if GLUT + needs to exit. + + Note that the __glut*WithExit routines should NEVER be called directly. + To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ + +/* XXX This is from Win32's */ +# if !defined(_MSC_VER) && !defined(__cdecl) + /* Define __cdecl for non-Microsoft compilers. */ +# define __cdecl +# define GLUT_DEFINED___CDECL +# endif +# ifndef _CRTIMP +# ifdef _NTSDK + /* Definition compatible with NT SDK */ +# define _CRTIMP +# else + /* Current definition */ +# ifdef _DLL +# define _CRTIMP __declspec(dllimport) +# else +# define _CRTIMP +# endif +# endif +# define GLUT_DEFINED__CRTIMP +# endif + +/* GLUT API entry point declarations for Win32. */ +# ifdef GLUT_BUILDING_LIB +# define GLUTAPI __declspec(dllexport) +# else +# ifdef _DLL +# define GLUTAPI __declspec(dllimport) +# else +# define GLUTAPI extern +# endif +# endif + +/* GLUT callback calling convention for Win32. */ +# define GLUTCALLBACK __cdecl + +#endif /* _WIN32 */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) +# ifndef GLUT_BUILDING_LIB +extern _CRTIMP void __cdecl exit(int); +# endif +#else +/* non-Win32 case. */ +/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */ +# define APIENTRY +# define GLUT_APIENTRY_DEFINED +# define CALLBACK +/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */ +# define GLUTAPI extern +# define GLUTCALLBACK +/* Prototype exit for the non-Win32 case (see above). */ +extern void exit(int); +#endif + +/** + GLUT API revision history: + + GLUT_API_VERSION is updated to reflect incompatible GLUT + API changes (interface changes, semantic changes, deletions, + or additions). + + GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 + + GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, + extension. Supports new input devices like tablet, dial and button + box, and Spaceball. Easy to query OpenGL extensions. + + GLUT_API_VERSION=3 glutMenuStatus added. + + GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, + glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic + video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, + glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, + glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). +**/ +#ifndef GLUT_API_VERSION /* allow this to be overriden */ +#define GLUT_API_VERSION 3 +#endif + +/** + GLUT implementation revision history: + + GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT + API revisions and implementation revisions (ie, bug fixes). + + GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of + GLUT Xlib-based implementation. 11/29/94 + + GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of + GLUT Xlib-based implementation providing GLUT version 2 + interfaces. + + GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 + + GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 + + GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 + + GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 + + GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner + and video resize. 1/3/97 + + GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. + + GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. + + GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. + + GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. + + GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. + + GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa +**/ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#define GLUT_XLIB_IMPLEMENTATION 15 +#endif + +/* Display mode bit masks. */ +#define GLUT_RGB 0 +#define GLUT_RGBA GLUT_RGB +#define GLUT_INDEX 1 +#define GLUT_SINGLE 0 +#define GLUT_DOUBLE 2 +#define GLUT_ACCUM 4 +#define GLUT_ALPHA 8 +#define GLUT_DEPTH 16 +#define GLUT_STENCIL 32 +#if (GLUT_API_VERSION >= 2) +#define GLUT_MULTISAMPLE 128 +#define GLUT_STEREO 256 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_LUMINANCE 512 +#endif + +/* Mouse buttons. */ +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 + +/* Mouse button state. */ +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +#if (GLUT_API_VERSION >= 2) +/* function keys */ +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +/* directional keys */ +#define GLUT_KEY_LEFT 100 +#define GLUT_KEY_UP 101 +#define GLUT_KEY_RIGHT 102 +#define GLUT_KEY_DOWN 103 +#define GLUT_KEY_PAGE_UP 104 +#define GLUT_KEY_PAGE_DOWN 105 +#define GLUT_KEY_HOME 106 +#define GLUT_KEY_END 107 +#define GLUT_KEY_INSERT 108 +#endif + +/* Entry/exit state. */ +#define GLUT_LEFT 0 +#define GLUT_ENTERED 1 + +/* Menu usage state. */ +#define GLUT_MENU_NOT_IN_USE 0 +#define GLUT_MENU_IN_USE 1 + +/* Visibility state. */ +#define GLUT_NOT_VISIBLE 0 +#define GLUT_VISIBLE 1 + +/* Window status state. */ +#define GLUT_HIDDEN 0 +#define GLUT_FULLY_RETAINED 1 +#define GLUT_PARTIALLY_RETAINED 2 +#define GLUT_FULLY_COVERED 3 + +/* Color index component selection values. */ +#define GLUT_RED 0 +#define GLUT_GREEN 1 +#define GLUT_BLUE 2 + +#if defined(_WIN32) +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN ((void*)0) +#define GLUT_STROKE_MONO_ROMAN ((void*)1) + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 ((void*)2) +#define GLUT_BITMAP_8_BY_13 ((void*)3) +#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) +#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 ((void*)6) +#define GLUT_BITMAP_HELVETICA_12 ((void*)7) +#define GLUT_BITMAP_HELVETICA_18 ((void*)8) +#endif +#else +/* Stroke font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutStrokeRoman; +GLUTAPI void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* Bitmap font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutBitmap9By15; +GLUTAPI void *glutBitmap8By13; +GLUTAPI void *glutBitmapTimesRoman10; +GLUTAPI void *glutBitmapTimesRoman24; +GLUTAPI void *glutBitmapHelvetica10; +GLUTAPI void *glutBitmapHelvetica12; +GLUTAPI void *glutBitmapHelvetica18; + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) +#endif +#endif + +/* glutGet parameters. */ +#define GLUT_WINDOW_X ((GLenum) 100) +#define GLUT_WINDOW_Y ((GLenum) 101) +#define GLUT_WINDOW_WIDTH ((GLenum) 102) +#define GLUT_WINDOW_HEIGHT ((GLenum) 103) +#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104) +#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105) +#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106) +#define GLUT_WINDOW_RED_SIZE ((GLenum) 107) +#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108) +#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109) +#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110) +#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111) +#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112) +#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113) +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114) +#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115) +#define GLUT_WINDOW_RGBA ((GLenum) 116) +#define GLUT_WINDOW_PARENT ((GLenum) 117) +#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118) +#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119) +#if (GLUT_API_VERSION >= 2) +#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120) +#define GLUT_WINDOW_STEREO ((GLenum) 121) +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_WINDOW_CURSOR ((GLenum) 122) +#endif +#define GLUT_SCREEN_WIDTH ((GLenum) 200) +#define GLUT_SCREEN_HEIGHT ((GLenum) 201) +#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202) +#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203) +#define GLUT_MENU_NUM_ITEMS ((GLenum) 300) +#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400) +#define GLUT_INIT_WINDOW_X ((GLenum) 500) +#define GLUT_INIT_WINDOW_Y ((GLenum) 501) +#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502) +#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503) +#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504) +#if (GLUT_API_VERSION >= 2) +#define GLUT_ELAPSED_TIME ((GLenum) 700) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123) +#endif + +#if (GLUT_API_VERSION >= 2) +/* glutDeviceGet parameters. */ +#define GLUT_HAS_KEYBOARD ((GLenum) 600) +#define GLUT_HAS_MOUSE ((GLenum) 601) +#define GLUT_HAS_SPACEBALL ((GLenum) 602) +#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603) +#define GLUT_HAS_TABLET ((GLenum) 604) +#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605) +#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606) +#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607) +#define GLUT_NUM_DIALS ((GLenum) 608) +#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610) +#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611) +#define GLUT_HAS_JOYSTICK ((GLenum) 612) +#define GLUT_OWNS_JOYSTICK ((GLenum) 613) +#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614) +#define GLUT_JOYSTICK_AXES ((GLenum) 615) +#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616) +#endif + +#if (GLUT_API_VERSION >= 3) +/* glutLayerGet parameters. */ +#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800) +#define GLUT_LAYER_IN_USE ((GLenum) 801) +#define GLUT_HAS_OVERLAY ((GLenum) 802) +#define GLUT_TRANSPARENT_INDEX ((GLenum) 803) +#define GLUT_NORMAL_DAMAGED ((GLenum) 804) +#define GLUT_OVERLAY_DAMAGED ((GLenum) 805) + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* glutVideoResizeGet parameters. */ +#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900) +#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901) +#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902) +#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903) +#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904) +#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905) +#define GLUT_VIDEO_RESIZE_X ((GLenum) 906) +#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907) +#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908) +#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909) +#endif + +/* glutUseLayer parameters. */ +#define GLUT_NORMAL ((GLenum) 0) +#define GLUT_OVERLAY ((GLenum) 1) + +/* glutGetModifiers return mask. */ +#define GLUT_ACTIVE_SHIFT 1 +#define GLUT_ACTIVE_CTRL 2 +#define GLUT_ACTIVE_ALT 4 + +/* glutSetCursor parameters. */ +/* Basic arrows. */ +#define GLUT_CURSOR_RIGHT_ARROW 0 +#define GLUT_CURSOR_LEFT_ARROW 1 +/* Symbolic cursor shapes. */ +#define GLUT_CURSOR_INFO 2 +#define GLUT_CURSOR_DESTROY 3 +#define GLUT_CURSOR_HELP 4 +#define GLUT_CURSOR_CYCLE 5 +#define GLUT_CURSOR_SPRAY 6 +#define GLUT_CURSOR_WAIT 7 +#define GLUT_CURSOR_TEXT 8 +#define GLUT_CURSOR_CROSSHAIR 9 +/* Directional cursors. */ +#define GLUT_CURSOR_UP_DOWN 10 +#define GLUT_CURSOR_LEFT_RIGHT 11 +/* Sizing cursors. */ +#define GLUT_CURSOR_TOP_SIDE 12 +#define GLUT_CURSOR_BOTTOM_SIDE 13 +#define GLUT_CURSOR_LEFT_SIDE 14 +#define GLUT_CURSOR_RIGHT_SIDE 15 +#define GLUT_CURSOR_TOP_LEFT_CORNER 16 +#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 +/* Inherit from parent window. */ +#define GLUT_CURSOR_INHERIT 100 +/* Blank cursor. */ +#define GLUT_CURSOR_NONE 101 +/* Fullscreen crosshair (if available). */ +#define GLUT_CURSOR_FULL_CROSSHAIR 102 +#endif + +/* GLUT initialization sub-API. */ +GLUTAPI void APIENTRY glutInit(int *argcp, char **argv); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } +#define glutInit glutInit_ATEXIT_HACK +#endif +#endif +GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutInitDisplayString(const char *string); +#endif +GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y); +GLUTAPI void APIENTRY glutInitWindowSize(int width, int height); +GLUTAPI void APIENTRY glutMainLoop(void); + +/* GLUT window sub-API. */ +GLUTAPI int APIENTRY glutCreateWindow(const char *title); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } +#define glutCreateWindow glutCreateWindow_ATEXIT_HACK +#endif +#endif +GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); +GLUTAPI void APIENTRY glutDestroyWindow(int win); +GLUTAPI void APIENTRY glutPostRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void APIENTRY glutPostWindowRedisplay(int win); +#endif +GLUTAPI void APIENTRY glutSwapBuffers(void); +GLUTAPI int APIENTRY glutGetWindow(void); +GLUTAPI void APIENTRY glutSetWindow(int win); +GLUTAPI void APIENTRY glutSetWindowTitle(const char *title); +GLUTAPI void APIENTRY glutSetIconTitle(const char *title); +GLUTAPI void APIENTRY glutPositionWindow(int x, int y); +GLUTAPI void APIENTRY glutReshapeWindow(int width, int height); +GLUTAPI void APIENTRY glutPopWindow(void); +GLUTAPI void APIENTRY glutPushWindow(void); +GLUTAPI void APIENTRY glutIconifyWindow(void); +GLUTAPI void APIENTRY glutShowWindow(void); +GLUTAPI void APIENTRY glutHideWindow(void); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void APIENTRY glutFullScreen(void); +GLUTAPI void APIENTRY glutSetCursor(int cursor); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutWarpPointer(int x, int y); +#endif + +/* GLUT overlay sub-API. */ +GLUTAPI void APIENTRY glutEstablishOverlay(void); +GLUTAPI void APIENTRY glutRemoveOverlay(void); +GLUTAPI void APIENTRY glutUseLayer(GLenum layer); +GLUTAPI void APIENTRY glutPostOverlayRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win); +#endif +GLUTAPI void APIENTRY glutShowOverlay(void); +GLUTAPI void APIENTRY glutHideOverlay(void); +#endif + +/* GLUT menu sub-API. */ +GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } +#define glutCreateMenu glutCreateMenu_ATEXIT_HACK +#endif +#endif +GLUTAPI void APIENTRY glutDestroyMenu(int menu); +GLUTAPI int APIENTRY glutGetMenu(void); +GLUTAPI void APIENTRY glutSetMenu(int menu); +GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value); +GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu); +GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); +GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); +GLUTAPI void APIENTRY glutRemoveMenuItem(int item); +GLUTAPI void APIENTRY glutAttachMenu(int button); +GLUTAPI void APIENTRY glutDetachMenu(int button); + +/* GLUT window callback sub-API. */ +GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); +GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); +GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); +#if (GLUT_API_VERSION >= 2) +GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); +GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); +GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); +#endif +#endif +#endif + +/* GLUT color index sub-API. */ +GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); +GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component); +GLUTAPI void APIENTRY glutCopyColormap(int win); + +/* GLUT state retrieval sub-API. */ +GLUTAPI int APIENTRY glutGet(GLenum type); +GLUTAPI int APIENTRY glutDeviceGet(GLenum type); +#if (GLUT_API_VERSION >= 2) +/* GLUT extension support sub-API */ +GLUTAPI int APIENTRY glutExtensionSupported(const char *name); +#endif +#if (GLUT_API_VERSION >= 3) +GLUTAPI int APIENTRY glutGetModifiers(void); +GLUTAPI int APIENTRY glutLayerGet(GLenum type); +#endif + +/* GLUT font sub-API */ +GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character); +GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character); +GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character); +GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string); +GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string); +#endif + +/* GLUT pre-built models sub-API */ +GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutWireCube(GLdouble size); +GLUTAPI void APIENTRY glutSolidCube(GLdouble size); +GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void APIENTRY glutWireDodecahedron(void); +GLUTAPI void APIENTRY glutSolidDodecahedron(void); +GLUTAPI void APIENTRY glutWireTeapot(GLdouble size); +GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size); +GLUTAPI void APIENTRY glutWireOctahedron(void); +GLUTAPI void APIENTRY glutSolidOctahedron(void); +GLUTAPI void APIENTRY glutWireTetrahedron(void); +GLUTAPI void APIENTRY glutSolidTetrahedron(void); +GLUTAPI void APIENTRY glutWireIcosahedron(void); +GLUTAPI void APIENTRY glutSolidIcosahedron(void); + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* GLUT video resize sub-API. */ +GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param); +GLUTAPI void APIENTRY glutSetupVideoResizing(void); +GLUTAPI void APIENTRY glutStopVideoResizing(void); +GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height); +GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height); + +/* GLUT debugging sub-API. */ +GLUTAPI void APIENTRY glutReportErrors(void); +#endif + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +/* GLUT device control sub-API. */ +/* glutSetKeyRepeat modes. */ +#define GLUT_KEY_REPEAT_OFF 0 +#define GLUT_KEY_REPEAT_ON 1 +#define GLUT_KEY_REPEAT_DEFAULT 2 + +/* Joystick button masks. */ +#define GLUT_JOYSTICK_BUTTON_A 1 +#define GLUT_JOYSTICK_BUTTON_B 2 +#define GLUT_JOYSTICK_BUTTON_C 4 +#define GLUT_JOYSTICK_BUTTON_D 8 + +GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore); +GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode); +GLUTAPI void APIENTRY glutForceJoystickFunc(void); + +/* GLUT game mode sub-API. */ +/* glutGameModeGet. */ +#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0) +#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1) +#define GLUT_GAME_MODE_WIDTH ((GLenum) 2) +#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3) +#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4) +#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5) +#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6) + +GLUTAPI void APIENTRY glutGameModeString(const char *string); +GLUTAPI int APIENTRY glutEnterGameMode(void); +GLUTAPI void APIENTRY glutLeaveGameMode(void); +GLUTAPI int APIENTRY glutGameModeGet(GLenum mode); +#endif + +#ifdef __cplusplus +} + +#endif + +#ifdef GLUT_APIENTRY_DEFINED +# undef GLUT_APIENTRY_DEFINED +# undef APIENTRY +#endif + +#ifdef GLUT_WINGDIAPI_DEFINED +# undef GLUT_WINGDIAPI_DEFINED +# undef WINGDIAPI +#endif + +#ifdef GLUT_DEFINED___CDECL +# undef GLUT_DEFINED___CDECL +# undef __cdecl +#endif + +#ifdef GLUT_DEFINED__CRTIMP +# undef GLUT_DEFINED__CRTIMP +# undef _CRTIMP +#endif + +#endif /* __glut_h__ */ diff --git a/samples/glut/README-win32.txt b/samples/glut/README-win32.txt index 5e22e9789..f3c1cbaa5 100644 --- a/samples/glut/README-win32.txt +++ b/samples/glut/README-win32.txt @@ -1,613 +1,613 @@ - - - GLUT for Win32 README - --------------------- - - -VERSION/INFO: - - This is GLUT for Win32 version 3.7.6 as of Nov 8th 2001. - See the COPYRIGHT section for distribution and copyright notices. - Send all bug reports and questions for this version of GLUT to - Nate Robins [nate@pobox.com]. - - For more information about GLUT for Win32, see the web page: - www.pobox.com/~nate/glut.html or subscribe to the GLUT for Win32 - mailing list by sending e-mail to majordomo@perp.com with - "subscribe glut" in the body of the message. - - For general information about GLUT, see the GLUT web page: - http://reality.sgi.com/opengl/glut3/glut3.html and be sure to - check the GLUT FAQ first for any questions that you may have: - http://reality.sgi.com/opengl/glut3/glut-faq.html - - -COMPILING/INSTALLATION: - - o Precompiled versions of the DLL and import library can be - found on the GLUT for Win32 web page mentioned above. - - o Microsoft Developer Studio 6 workspace and project files have - been included in the source code distribution. - - To build the glut dll: - First, open Microsoft Developer Studio. - Then, select File -> Open Workspace and find the glut.dsw file - in the file dialog and double-click on it. - Finally, select Build -> Build glut32.dll. - When the build is finished, it will copy: - glut32.dll to %WinDir%\System, - glut32.lib to $(MSDevDir)\..\..\VC98\lib, and - glut.h to $(MSDevDir)\..\..\VC98\include\GL. - - Additional workspace files have been included in the progs, test - and lib directories to build the progs, tests and libs respectively. - - -BORLAND NOTES: - - From what I understand, Borland supplies a utility that - converts Microsoft Visual C++ .libs into Borland compatible - files. Therefore, the best method for Borland users is - probably to get the precompiled versions of the library and - convert the library. To create an import library for Borland - from the DLLs, use the following command (from a command prompt): - IMPLIB glut32.lib glut32.dll - If IMPLIB crashes when called this way, try - IMPLIB glut32.lib glut32.def - using the glut32.def file in this distribution. - - -FORTRAN NOTES: - - Bill Mitchell [william.mitchell@nist.gov] has put considerable - effort into getting GLUT to work with different compilers for - Fortran 90. He indicates that you should copy the f90glut.h - file to your $(MSDevDir)\..\..\VC98\include\GL directory. - Then, just build GLUT as usual. The Fortran 90 interface, f90gl, - can be obtained at http://math.nist.gov/f90gl and contains - installation instructions and usage examples. - - -MISC NOTES: - - o Overlay support is not implemented, nor are there any plans to - implement it in the near future. - - o To customize the windows icon, you can use the resource name - GLUT_ICON. For example, create an icon named "glut.ico", and - create a file called glut.rc that contains the following: - GLUT_ICON ICON glut.ico - then compile the glut.rc file with the following: - rc /r glut - and link the resulting glut.res file into your executable - (just like you would an object file). - Alternatively, you can simply add the glut.rc file to your - project if you are using Microsoft Developer Studio. - - -IMPLEMENTATION DEPENDENT DIFFERENCES: - - There are a few differences between the Win32 version of GLUT - and the X11 version of GLUT. Those are outlined here. Note - that MOST of these differences are allowed by the GLUT - specification. Bugs and unsupported features are outlined in - the UNSUPPORTED/BUGS section. - - o glutInit: - The following command line options have no meaning (and are - ignored) in GLUT for Win32: - -display, -indirect, -direct, -sync. - - o glutInitWindowPosition, glutPositionWindow: - Win32 has two different coordinate systems for windows. - One is in terms of client space and the other is the whole - window space (including the decorations). If you - glutPositionWindow(0, 0), GLUT for Win32 will place the - window CLIENT area at 0, 0. This will cause the window - decorations (title bar and left edge) to be OFF-SCREEN, but - it gives the user the most flexibility in positioning. - HOWEVER, if the user specifies glutInitWindowPosition(0, 0), - the window is placed relative to window space at 0, 0. - This will cause the window to be opened in the upper left - corner with all the decorations showing. This behaviour is - acceptable under the current GLUT specification. - - o glutSetIconTitle, glutSetWindowTitle: - There is no separation between Icon title and Window title - in Win32. Therefore, setting an icon title in Win32 has - no effect. - - o glutSetCursor: - As indicated in the GLUT specification, cursors may be - different on different platforms. This is the case in GLUT - for Win32. For the most part, the cursors will match the - meaning, but not necessarily the shape. Notable exceptions - are the GLUT_CURSOR_INFO & GLUT_CURSOR_SPRAY which use the - crosshair cursor and the GLUT_CURSOR_CYCLE which uses the - 'no' or 'destroy' cursor in Win32. - - o glutVisibilityFunc: - Win32 seems to be unable to determine if a window is fully - obscured. Therefore, the visibility of a GLUT window is - only reflected by its Iconic, Hidden or Shown state. That - is, even if a window is fully obscured, in GLUT for Win32, - it is still "visible". - - o glutEntryFunc: - Window Focus is handled differently in Win32 and X. - Specifically, the "window manager" in Win32 uses a "click to - focus" policy. That is, in order for a window to receive - focus, a mouse button must be clicked in it. Likewise, in - order for a window to lose focus, a mouse button must be - clicked outside the window (or in another window). - Therefore, the Enter and Leave notification provided by GLUT - may behave differently in the Win32 and in X11 versions. - There is a viable workaround for this. A program called - "Tweak UI" is provided by Microsoft which can be used to - change the focus policy in Win32 to "focus follows mouse". - It is available from the Microsoft Web Pages: - http://www.microsoft.com/windows/software/PowerToy.htm - - o glutCopyColormap: - GLUT for Win32 always copies the colormap. There is never - any sharing of colormaps. This is probably okay, since - Win32 merges the logical palette and the physical palette - anyway, so even if there are two windows with totally - different colors in their colormaps, Win32 will find a - (hopefully) good match between them. - - o glutIdleFunc + menus: - The glut idle function will NOT be called when a menu is - active. This causes all animation to stop when a menu is - active (in general, this is probably okay). Timer - functions will still fire, however. If the timer callback - draws into the rendering context, the drawing will not show - up until after the menu has finished, though. - - -UNSUPPORTED/BUGS: - - o glutAttachMenu: - Win32 only likes to work with left and right mouse buttons. - Especially so with popup menus. Therefore, when attaching - the menu to the middle mouse button, the LEFT mouse button - must be used to select from the menu. - - o glutSpaceball*, glutButtonBox*, glutTablet*, glutDials*: - None of the special input devices are supported at this - time. - - o When resizing or moving a GLUT for Win32 window, no updating - is performed. This causes the window to leave "tracks" on - the screen when getting bigger or when previously obscured - parts are being revealed. I put in a bit of a kludgy - workaround for those that absolutely can't have the weird - lines. The reshape callback is called multiple times for - reshapes. Therefore, in the reshape callback, some drawing - can be done. It should probably be limited to a color buffer - clear. - - o The video resizing capabilities of GLUT 3.3+ for X11 is - currently unimplemented (this is probably ok, since it - really isn't part of the spec until 4.0). I doubt that - this will ever be part of GLUT for Win32, since there is no - hardware to support it. A hack could simply change the - resolution of the desktop. - - -CHANGES/FIXES: - - (Nov 8, '01) - x Released 3.7.6 - - (Nov 8, '01) - x Changed fullscreen mode from TOPMOST back to simply TOP, since - (it turns out) many people use windows atop a GLUT window. - - (Nov 8, '01) - x Added code to prevent CPU spiking when no idle function is - registered. Otherwise, if an idle function is registered, spike - CPU so that the idle function gets all the attention it needs and - if this is a problem on the program side, the user can stick a - sleep() in their idle function. I believe that this strikes the - best balance betweeen GLUT being fast, and also being "nice" to - other processes. Thanks to James Wright for reporting this bug. - - (Nov 8, '01) - x Fixed bug in motion callback handler which wasn't setting the - current window, so multiple window apps (e.g., any GLUI app) - wouldn't get the callback correctly. - - (Oct 4, '01) - x Fixed bug in glutEnterGameMode() that caused new windows to not - be in "fullscreen" mode, so they got window decorations. - - (Oct 4, '01) - x Fixed bug in glutEnterGameMode() that caused new windows to not - be in "fullscreen" mode, so they got window decorations. - - (Oct 3, '01) - x Fixed bug in getVisualInfoFromString(): visuals not reloaded on - display mode change. Reload visuals each time they are queried. - This fixes a problem with Win32 because the list of availabe Visuals - (Pixelformats) changes after a change in displaymode. The problem - occurs when switching to gamemode and back. Thanks to Michael - Wimmer for pointing this out & providing the fix. - - (Oct 3, '01) - x Fixed bug in XGetVisualInfo(): pixelformats enumerated incorrectly. - Passing 0 as a pixelformat index to DescribePixelFormat gives - unpredictible results (e.g., this fails on the Voodoo opengl32.dll - and always reports 0 as the last available pixelformat index). - Thanks to Michael Wimmer for pointing this out & providing the fix. - - (Oct 3, '01) - x Fixed bug in glXGetConfig(): pixelformats enumerated incorrectly. The - test was OpenGL support OR draw to window, but should be AND. Thanks - to Michael Wimmer for pointing this out & providing the fix. - - (Sep 28, '01) - x Fixed glutChangeToSubMenu()/glutChangeToMenuEntry() bug where if you - went back and forth between a submenu and a plain entry, the submenu - wouldn't be updated properly. - - (Sep 28, '01) - x glutSetIconTitle() is now a nop. - - (Sep 28, '01) - x glutFullScreen() now sets the window as TOPMOST, therefore, the - window will always be on top (this essentially disables alt-tabbing). - - (Sep 28, '01) - x The key repeat ignore flag is now honored correctly. - - (Sep 28, '01) - x Key presses are now reported more accurately and fully, in - particular, modified up events (i.e., SHIFT-2) are now reported - correctly. - - (Sep 28, '01) - x Subwindows nested arbitrarily deep get their keyboard callbacks - correctly now. - - (Sep 28, '01) - x Major rewrite of the window procedure code to clean it up and make - way for other bug fixes. - - (Sep 23, '01) - x Fixed noof example program to use RAND_MAX instead of assumed - max of 2147483647.0. (Now it looks _much_ better!) - - (Sep 22, '01) - x Fixed sunlight example program. globe.raw data file was corrupt, - added a new one. - - (Sep 22, '01) - x Fixed zcomposite example program to print message if overlay - support is not found (instead of crashing). - - (Jan 22, '01) - x Fixed malloc(0) bug in Win32 version of XGetVisualInfo. Thanks - to Kekoa Proudfoot for bringing this to my attention. - - (Dec 12, '00) - x Added data files for the advanced & advanced97 programs. - - (Dec 12, '00) - x Added Developer Studio 6 project and workspace files for pretty - much everything (the stuff left out was usually unix specific). - - (Dec 7, '00) - x Fixed several compilation problems & corrupt files. Thanks to - Alexander Stohr for bringing these to my attention and providing - detailed fixes. - - (Dec 6, '00) - x Fixed compiler support for lcc. Thanks to Gordon for bringing - this to my attention and debugging fixes. - - (Nov 8, '00) - x Fixed submenu problem (sometimes the menu callback was not - called for valid items). Thanks to Michael Keeley. - - (Oct 16, '00) - x Corrected corrupt duck.iv file. Thanks to Jon Willeke for finding - this problem. - - (Sept 27, '00) - x Fixed bug in processWorkList that could cause a hang. Thanks to - Bill Volz & Daniel Azuma. - - (Sept 26, '00) - x Added mui DLL project file (thanks to DMWeldy@ugsolutions.com). - - (Sept 9, '00) - x Fixed Delete key bug (crash when no keyboard callback was - registered, but a special key callback was). Thanks to - Kent Bowling (kent_bowling@hotmail.com) for finding this bug. - - (May 18, '00) - x Fixed subwindow keyboard callbacks. - - (May 22, '97) - o Menus don't work under Windows 95 - x Fixed! Added a unique identifier to each menu item, and a - search function to grab a menu item given the unique identifier. - - (May 21, '97) - o A few minor bug fixes here and there. - x Thanks to Bruce Silberman and Chris Vale for their help with - this. We now have a DLL! - - (Apr 25, '97) - o DLL version of the library is coming (as soon as I figure out - how to do it -- if you know, let me know). - x Thanks to Bruce Silberman and Chris Vale for their help with - this. We now have a DLL! - - (Apr 24, '97) - x Added returns to KEY_DOWN etc messages so that the F10 key - doesn't toggle the system menu anymore. - - (Apr 7, '97) - o Palette is incorrect for modes other than TrueColor. - x Fixed this by forcing a default palette in modes that aren't - Truecolor in order to 'simulate' it. The applications - program shouldn't have to do this IMHO, but I guess we - can't argue with Microsoft (well, we can, but what good - will it do?). - - (Apr 2, '97) - x Added glut.ide file for Borland users. - - (Apr 2, '97) - x Fixed a bug in the WM_QUERYNEWPALETTE message. Wasn't - checking for a null colormap, then de-ref'd it. Oops. - - (Mar 13, '97) - o glutTimerFunc: - Currently, GLUT for Win32 programs busy waits when there is - an outstanding timer event (i.e., there is no select() - call). I haven't found this to be a problem, but I plan to - fix it just because I can't bear the thought of a busy wait. - x Added a timer event and a wait in the main loop. This fixes - the CPU spike. - - (Mar 11, '97) - x Fixed subwindow visibility. The visibility callback of - subwindows wasn't being called, now it is. - - (Mar 11, '97) - o glutGetHDC, glutGetHWND: - In order to support additional dialog boxes, wgl fonts, and - a host of other Win32 dependent structures, two functions - have been added that operate on the current window in GLUT. - The first (glutGetHDC) returns a handle to the current - windows device context. The second (glutGetHWND) returns - handle to the current window. - x Took these out to preserve GLUT portability. - - (Mar 11, '97) - x Fixed the glutWarpPointer() coordinates. Were relative to - the screen, now relative to window (client area) origin - (which is what they're supposed to be). - - (Mar 11, '97) - o glutCreateMenu, glutIdleFunc: - Menu's are modal in Win32. That is, they don't allow any - messages to be processed while they are up. Therefore, if - an idle function exists, it will not be called while - processing a menu. - x Fixed! I've put in a timer function that fires every - millisecond while a menu is up. The timer function handles - idle and timer events only (which should be the only - functions that are firing when a menu is up anyway). - - (Mar 7 '97) - x Fixed minor bugs tracked down by the example programs. - - (Mar 6, '97) - x Merged 3.3 GLUT for X11 into 3.2 GLUT for Win32. New code - structure allows for EASY merging! - - o In Win32, the parent gets the right to set the cursor of - any of its children. Therefore, a child windows cursor - will 'blink' between its cursor and its parent. - x Fixed this by checking whether the cursor is in a child - window or not. - - (Feb 28 '97) - o On initial bringup apps are getting 2 display callbacks. - x Fixed by the Fev 28 re-write. - - o Some multiple window (not subwindow) functionality is messed up. - See the sphere.exe program. - x Fixed by the Feb 28 re-write. - - o GLUT for Win32 supports color index mode ONLY in a paletted - display mode (i.e., 256 or 16 color mode). - x Fixed this in the re-write. If you can get a color index - visual (pixel format) you can use color index mode. - - (Feb 28 '97) - o Quite a few bugs (and incompatibilities) were being caused - by the structure that I used in the previous port of GLUT. - Therefore I decided that it would be best to "get back to - the roots". I re-implemented most of glut trying to stick - with the structure layed out by Mark. The result is a much - more stable version that passes ALL (!) (except overlay) - the tests provided by Mark. In addition, this new - structure will allow future enhancements by Mark to be - integrated much more quickly into the Win32 version. Also, - I'm now ordering the bugs in reverse, so that the most - recently fixed appear at the top of the list. - - (9/8/96) - o Changed the glutGetModifiers code to produce an error if not - called in the core input callbacks. - - (9/11/96) - o If the alt key is pressed with more than one other modifier key - it acts as if it is stuck -- it stays selected until pressed - and released again. - x Fixed. - - (9/12/96) - o When a submenu is attached to a menu, sometimes a GPF occurs. - Fixed. Needed to set the submenu before referencing it's members. - - o Kenny: Also, one little problem, I attached the menu to the - right-button, but when the left-button is pressed I detach - it to give the right-button new meaning; if I pop-up the menu and I - don't want to select anything, like most users, I click off of the - menu to make it disappear. When I do this, I get a GLUT error and - the program terminates because I am altering the menu attachment - from within the button press while the menu is active. - x Fixed. Needed to finish the menu when the user presses the button, - not just when a button is released. - - o GLUT for Win32 emulates a middle mouse button by checking if - both mouse buttons are down. This causes a lot of problems with - the menu and other multiple mouse button things. - x Fixed. No more middle mouse button emulation. Perhaps it would - be a good idea to emulate the middle mouse button (if not present) - with a key? - - (9/15/96) - o Added code to accept a user defined icon. If no icon is provided, - a default icon is loaded. - - (9/19/96) - o Shane: Command line options seem to be screwed up. (9/13) - x Fixed. The geometry command line was broken, and so was the - gldebug command line. - - o Fixed a bug in the default glut reshape. It was looking for the - parent of the current window and GPF'ing if there wasn't a parent. - Put in a check for a parent, and if none is there, use the - child. - - o Idle function sucks up all processor cycles. (9/8/96) - x I don't know if this is avoidable. If you have a tight rendering - loop, it may be that the processor time is going to be sucked up - no matter what. You can add a sleep() to the end of your render - loop if you would like to yeild to other processes and you don't - care too much about the speed of your rendering loop. If you have - Hardware that supports OpenGL (like a 3Dpro card, or GLint card) - then this should be less of a problem, since it won't be rendering - in software. (9/11/96) - - o If a window is fully obscured by another window, the visibility - callback is NOT called. As far as I can tell, this is a limitation - of the Win32 api, but a workaround is being searched for. (9/8/96) - x Limitation of the Win32 API - - o Fixed the entry functions. They only work if the keyboard focus - changes. Therefore, in most Win32 systems, the mouse must be - pressed outside of the window to get a GLUT_LEFT message and - then pressed inside the window for a GLUT_ENTERED message. - - o Alt modifier key doesn't work with keyboard callback. (9/8/96) - x Probably okay, because the glut spec says that these keys can - be intercepted by the system (which the alt key is...) (9/11/96) - - (11/17/96) - o glutRemoveMenuItem() not working properly. - x Thanks to Gary (grc@maple.civeng.rutgers.edu) for the fix to - this one. - - o Timer functions are messed up. - x Thanks to Joseph Galbraith for the fix to this one. - - (12/9/96) - o One (minor) difference came up between the X version of glut - and the nt one which you should know about. It is not a new - problem, and it concerns co-ords returned to the pointer - callbacks. (glutMotionFunc, glutMouseFunc) - Under X, you get co-ords in the range 0 +/- 2^15, under NT - you get 0..2^16. This is only really a problem when moving - above or to the left of the window. - eg dragging one pixel ABOVE the window will give :- - under x11 : y = -1 - under nt : y = 2^16 -1 - x Put in fix provided by Shane Clauson. - - (12/17/96) - o Idle functions not working properly for multiple windows. - x Fixed this by posting an idle message to every window in the - window list when idle. - - (12/18/96) - o glutSetCursor() was misbehaving (lthomas@cco.caltech.edu). - x Win32 requires that the hCursor member of the window class - be set to NULL when the class is registered or whenever the - mouse is moved, the original cursor is replaced (go - figure!). Now sets the cursor whenever a WM_MOUSEMOVE message - is received, because the WM_SETCURSOR event resets the cursor - even when in the decoration area. - - o Geometry is not being handled quite right. The numbers don't - take into account the window decorations. That is, if I say - make a window 100x100, then the WHOLE window (not just the - client area) is 100x100. Therefore, the client (opengl) area - is smaller than 100x100. (9/8/96) - x Fixed. Added code to subtract the decoration size on glutGet() - and add the decoration size on glutReshapeWindow(). - - o Multiple glutPostRedisplay() calls are NOT being combined. - To get round the "coalesce" problem on glutPostRedisplay, - the easiest solution is to roll-your-own coalesce by - keeping a global "dirty" flag in the app (eg replace all - calls to glutPostRedisplay with image_dirty=TRUE;), and to - handle image_dirty with a single glutPostRedisplay in the - idle callback when required. (erk - but increases - performance for my particular app (a rendering engine on - the end of a pipleine with a stream of graphics updates) by - a couple of orders of magnitude ! ) (9/8/96) - x Added code to coalesce redisplays. Every idle cycle, a - check is made to see which windows need redisplay, if they - need it, a redisplay is posted. The glutPostRedisplay() - call is just a stub that sets a flag. - - -THANKS: - - Special thanks to the following people for extensive testing, - suggestions, fixes and help: - - Alexander Stohr - Shane Clauson - Kenny Hoff - Richard Readings - Paul McQuesten - Philip Winston - JaeWoo Ahn - Joseph Galbraith - Paula Higgins - Sam Fortin - Chris Vale - Bill Mitchell - - and of course, the original author of GLUT: - Mark Kilgard. - - and many others... - - -COPYRIGHT: - -The OpenGL Utility Toolkit distribution for Win32 (Windows NT & -Windows 95) contains source code modified from the original source -code for GLUT version 3.3 which was developed by Mark J. Kilgard. The -original source code for GLUT is Copyright 1997 by Mark J. Kilgard. -GLUT for Win32 is Copyright 1997 by Nate Robins and is not in the -public domain, but it is freely distributable without licensing fees. -It is provided without guarantee or warrantee expressed or implied. -It was ported with the permission of Mark J. Kilgard by Nate Robins. - -THIS SOURCE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -OpenGL (R) is a registered trademark of Silicon Graphics, Inc. + + + GLUT for Win32 README + --------------------- + + +VERSION/INFO: + + This is GLUT for Win32 version 3.7.6 as of Nov 8th 2001. + See the COPYRIGHT section for distribution and copyright notices. + Send all bug reports and questions for this version of GLUT to + Nate Robins [nate@pobox.com]. + + For more information about GLUT for Win32, see the web page: + www.pobox.com/~nate/glut.html or subscribe to the GLUT for Win32 + mailing list by sending e-mail to majordomo@perp.com with + "subscribe glut" in the body of the message. + + For general information about GLUT, see the GLUT web page: + http://reality.sgi.com/opengl/glut3/glut3.html and be sure to + check the GLUT FAQ first for any questions that you may have: + http://reality.sgi.com/opengl/glut3/glut-faq.html + + +COMPILING/INSTALLATION: + + o Precompiled versions of the DLL and import library can be + found on the GLUT for Win32 web page mentioned above. + + o Microsoft Developer Studio 6 workspace and project files have + been included in the source code distribution. + + To build the glut dll: + First, open Microsoft Developer Studio. + Then, select File -> Open Workspace and find the glut.dsw file + in the file dialog and double-click on it. + Finally, select Build -> Build glut32.dll. + When the build is finished, it will copy: + glut32.dll to %WinDir%\System, + glut32.lib to $(MSDevDir)\..\..\VC98\lib, and + glut.h to $(MSDevDir)\..\..\VC98\include\GL. + + Additional workspace files have been included in the progs, test + and lib directories to build the progs, tests and libs respectively. + + +BORLAND NOTES: + + From what I understand, Borland supplies a utility that + converts Microsoft Visual C++ .libs into Borland compatible + files. Therefore, the best method for Borland users is + probably to get the precompiled versions of the library and + convert the library. To create an import library for Borland + from the DLLs, use the following command (from a command prompt): + IMPLIB glut32.lib glut32.dll + If IMPLIB crashes when called this way, try + IMPLIB glut32.lib glut32.def + using the glut32.def file in this distribution. + + +FORTRAN NOTES: + + Bill Mitchell [william.mitchell@nist.gov] has put considerable + effort into getting GLUT to work with different compilers for + Fortran 90. He indicates that you should copy the f90glut.h + file to your $(MSDevDir)\..\..\VC98\include\GL directory. + Then, just build GLUT as usual. The Fortran 90 interface, f90gl, + can be obtained at http://math.nist.gov/f90gl and contains + installation instructions and usage examples. + + +MISC NOTES: + + o Overlay support is not implemented, nor are there any plans to + implement it in the near future. + + o To customize the windows icon, you can use the resource name + GLUT_ICON. For example, create an icon named "glut.ico", and + create a file called glut.rc that contains the following: + GLUT_ICON ICON glut.ico + then compile the glut.rc file with the following: + rc /r glut + and link the resulting glut.res file into your executable + (just like you would an object file). + Alternatively, you can simply add the glut.rc file to your + project if you are using Microsoft Developer Studio. + + +IMPLEMENTATION DEPENDENT DIFFERENCES: + + There are a few differences between the Win32 version of GLUT + and the X11 version of GLUT. Those are outlined here. Note + that MOST of these differences are allowed by the GLUT + specification. Bugs and unsupported features are outlined in + the UNSUPPORTED/BUGS section. + + o glutInit: + The following command line options have no meaning (and are + ignored) in GLUT for Win32: + -display, -indirect, -direct, -sync. + + o glutInitWindowPosition, glutPositionWindow: + Win32 has two different coordinate systems for windows. + One is in terms of client space and the other is the whole + window space (including the decorations). If you + glutPositionWindow(0, 0), GLUT for Win32 will place the + window CLIENT area at 0, 0. This will cause the window + decorations (title bar and left edge) to be OFF-SCREEN, but + it gives the user the most flexibility in positioning. + HOWEVER, if the user specifies glutInitWindowPosition(0, 0), + the window is placed relative to window space at 0, 0. + This will cause the window to be opened in the upper left + corner with all the decorations showing. This behaviour is + acceptable under the current GLUT specification. + + o glutSetIconTitle, glutSetWindowTitle: + There is no separation between Icon title and Window title + in Win32. Therefore, setting an icon title in Win32 has + no effect. + + o glutSetCursor: + As indicated in the GLUT specification, cursors may be + different on different platforms. This is the case in GLUT + for Win32. For the most part, the cursors will match the + meaning, but not necessarily the shape. Notable exceptions + are the GLUT_CURSOR_INFO & GLUT_CURSOR_SPRAY which use the + crosshair cursor and the GLUT_CURSOR_CYCLE which uses the + 'no' or 'destroy' cursor in Win32. + + o glutVisibilityFunc: + Win32 seems to be unable to determine if a window is fully + obscured. Therefore, the visibility of a GLUT window is + only reflected by its Iconic, Hidden or Shown state. That + is, even if a window is fully obscured, in GLUT for Win32, + it is still "visible". + + o glutEntryFunc: + Window Focus is handled differently in Win32 and X. + Specifically, the "window manager" in Win32 uses a "click to + focus" policy. That is, in order for a window to receive + focus, a mouse button must be clicked in it. Likewise, in + order for a window to lose focus, a mouse button must be + clicked outside the window (or in another window). + Therefore, the Enter and Leave notification provided by GLUT + may behave differently in the Win32 and in X11 versions. + There is a viable workaround for this. A program called + "Tweak UI" is provided by Microsoft which can be used to + change the focus policy in Win32 to "focus follows mouse". + It is available from the Microsoft Web Pages: + http://www.microsoft.com/windows/software/PowerToy.htm + + o glutCopyColormap: + GLUT for Win32 always copies the colormap. There is never + any sharing of colormaps. This is probably okay, since + Win32 merges the logical palette and the physical palette + anyway, so even if there are two windows with totally + different colors in their colormaps, Win32 will find a + (hopefully) good match between them. + + o glutIdleFunc + menus: + The glut idle function will NOT be called when a menu is + active. This causes all animation to stop when a menu is + active (in general, this is probably okay). Timer + functions will still fire, however. If the timer callback + draws into the rendering context, the drawing will not show + up until after the menu has finished, though. + + +UNSUPPORTED/BUGS: + + o glutAttachMenu: + Win32 only likes to work with left and right mouse buttons. + Especially so with popup menus. Therefore, when attaching + the menu to the middle mouse button, the LEFT mouse button + must be used to select from the menu. + + o glutSpaceball*, glutButtonBox*, glutTablet*, glutDials*: + None of the special input devices are supported at this + time. + + o When resizing or moving a GLUT for Win32 window, no updating + is performed. This causes the window to leave "tracks" on + the screen when getting bigger or when previously obscured + parts are being revealed. I put in a bit of a kludgy + workaround for those that absolutely can't have the weird + lines. The reshape callback is called multiple times for + reshapes. Therefore, in the reshape callback, some drawing + can be done. It should probably be limited to a color buffer + clear. + + o The video resizing capabilities of GLUT 3.3+ for X11 is + currently unimplemented (this is probably ok, since it + really isn't part of the spec until 4.0). I doubt that + this will ever be part of GLUT for Win32, since there is no + hardware to support it. A hack could simply change the + resolution of the desktop. + + +CHANGES/FIXES: + + (Nov 8, '01) + x Released 3.7.6 + + (Nov 8, '01) + x Changed fullscreen mode from TOPMOST back to simply TOP, since + (it turns out) many people use windows atop a GLUT window. + + (Nov 8, '01) + x Added code to prevent CPU spiking when no idle function is + registered. Otherwise, if an idle function is registered, spike + CPU so that the idle function gets all the attention it needs and + if this is a problem on the program side, the user can stick a + sleep() in their idle function. I believe that this strikes the + best balance betweeen GLUT being fast, and also being "nice" to + other processes. Thanks to James Wright for reporting this bug. + + (Nov 8, '01) + x Fixed bug in motion callback handler which wasn't setting the + current window, so multiple window apps (e.g., any GLUI app) + wouldn't get the callback correctly. + + (Oct 4, '01) + x Fixed bug in glutEnterGameMode() that caused new windows to not + be in "fullscreen" mode, so they got window decorations. + + (Oct 4, '01) + x Fixed bug in glutEnterGameMode() that caused new windows to not + be in "fullscreen" mode, so they got window decorations. + + (Oct 3, '01) + x Fixed bug in getVisualInfoFromString(): visuals not reloaded on + display mode change. Reload visuals each time they are queried. + This fixes a problem with Win32 because the list of availabe Visuals + (Pixelformats) changes after a change in displaymode. The problem + occurs when switching to gamemode and back. Thanks to Michael + Wimmer for pointing this out & providing the fix. + + (Oct 3, '01) + x Fixed bug in XGetVisualInfo(): pixelformats enumerated incorrectly. + Passing 0 as a pixelformat index to DescribePixelFormat gives + unpredictible results (e.g., this fails on the Voodoo opengl32.dll + and always reports 0 as the last available pixelformat index). + Thanks to Michael Wimmer for pointing this out & providing the fix. + + (Oct 3, '01) + x Fixed bug in glXGetConfig(): pixelformats enumerated incorrectly. The + test was OpenGL support OR draw to window, but should be AND. Thanks + to Michael Wimmer for pointing this out & providing the fix. + + (Sep 28, '01) + x Fixed glutChangeToSubMenu()/glutChangeToMenuEntry() bug where if you + went back and forth between a submenu and a plain entry, the submenu + wouldn't be updated properly. + + (Sep 28, '01) + x glutSetIconTitle() is now a nop. + + (Sep 28, '01) + x glutFullScreen() now sets the window as TOPMOST, therefore, the + window will always be on top (this essentially disables alt-tabbing). + + (Sep 28, '01) + x The key repeat ignore flag is now honored correctly. + + (Sep 28, '01) + x Key presses are now reported more accurately and fully, in + particular, modified up events (i.e., SHIFT-2) are now reported + correctly. + + (Sep 28, '01) + x Subwindows nested arbitrarily deep get their keyboard callbacks + correctly now. + + (Sep 28, '01) + x Major rewrite of the window procedure code to clean it up and make + way for other bug fixes. + + (Sep 23, '01) + x Fixed noof example program to use RAND_MAX instead of assumed + max of 2147483647.0. (Now it looks _much_ better!) + + (Sep 22, '01) + x Fixed sunlight example program. globe.raw data file was corrupt, + added a new one. + + (Sep 22, '01) + x Fixed zcomposite example program to print message if overlay + support is not found (instead of crashing). + + (Jan 22, '01) + x Fixed malloc(0) bug in Win32 version of XGetVisualInfo. Thanks + to Kekoa Proudfoot for bringing this to my attention. + + (Dec 12, '00) + x Added data files for the advanced & advanced97 programs. + + (Dec 12, '00) + x Added Developer Studio 6 project and workspace files for pretty + much everything (the stuff left out was usually unix specific). + + (Dec 7, '00) + x Fixed several compilation problems & corrupt files. Thanks to + Alexander Stohr for bringing these to my attention and providing + detailed fixes. + + (Dec 6, '00) + x Fixed compiler support for lcc. Thanks to Gordon for bringing + this to my attention and debugging fixes. + + (Nov 8, '00) + x Fixed submenu problem (sometimes the menu callback was not + called for valid items). Thanks to Michael Keeley. + + (Oct 16, '00) + x Corrected corrupt duck.iv file. Thanks to Jon Willeke for finding + this problem. + + (Sept 27, '00) + x Fixed bug in processWorkList that could cause a hang. Thanks to + Bill Volz & Daniel Azuma. + + (Sept 26, '00) + x Added mui DLL project file (thanks to DMWeldy@ugsolutions.com). + + (Sept 9, '00) + x Fixed Delete key bug (crash when no keyboard callback was + registered, but a special key callback was). Thanks to + Kent Bowling (kent_bowling@hotmail.com) for finding this bug. + + (May 18, '00) + x Fixed subwindow keyboard callbacks. + + (May 22, '97) + o Menus don't work under Windows 95 + x Fixed! Added a unique identifier to each menu item, and a + search function to grab a menu item given the unique identifier. + + (May 21, '97) + o A few minor bug fixes here and there. + x Thanks to Bruce Silberman and Chris Vale for their help with + this. We now have a DLL! + + (Apr 25, '97) + o DLL version of the library is coming (as soon as I figure out + how to do it -- if you know, let me know). + x Thanks to Bruce Silberman and Chris Vale for their help with + this. We now have a DLL! + + (Apr 24, '97) + x Added returns to KEY_DOWN etc messages so that the F10 key + doesn't toggle the system menu anymore. + + (Apr 7, '97) + o Palette is incorrect for modes other than TrueColor. + x Fixed this by forcing a default palette in modes that aren't + Truecolor in order to 'simulate' it. The applications + program shouldn't have to do this IMHO, but I guess we + can't argue with Microsoft (well, we can, but what good + will it do?). + + (Apr 2, '97) + x Added glut.ide file for Borland users. + + (Apr 2, '97) + x Fixed a bug in the WM_QUERYNEWPALETTE message. Wasn't + checking for a null colormap, then de-ref'd it. Oops. + + (Mar 13, '97) + o glutTimerFunc: + Currently, GLUT for Win32 programs busy waits when there is + an outstanding timer event (i.e., there is no select() + call). I haven't found this to be a problem, but I plan to + fix it just because I can't bear the thought of a busy wait. + x Added a timer event and a wait in the main loop. This fixes + the CPU spike. + + (Mar 11, '97) + x Fixed subwindow visibility. The visibility callback of + subwindows wasn't being called, now it is. + + (Mar 11, '97) + o glutGetHDC, glutGetHWND: + In order to support additional dialog boxes, wgl fonts, and + a host of other Win32 dependent structures, two functions + have been added that operate on the current window in GLUT. + The first (glutGetHDC) returns a handle to the current + windows device context. The second (glutGetHWND) returns + handle to the current window. + x Took these out to preserve GLUT portability. + + (Mar 11, '97) + x Fixed the glutWarpPointer() coordinates. Were relative to + the screen, now relative to window (client area) origin + (which is what they're supposed to be). + + (Mar 11, '97) + o glutCreateMenu, glutIdleFunc: + Menu's are modal in Win32. That is, they don't allow any + messages to be processed while they are up. Therefore, if + an idle function exists, it will not be called while + processing a menu. + x Fixed! I've put in a timer function that fires every + millisecond while a menu is up. The timer function handles + idle and timer events only (which should be the only + functions that are firing when a menu is up anyway). + + (Mar 7 '97) + x Fixed minor bugs tracked down by the example programs. + + (Mar 6, '97) + x Merged 3.3 GLUT for X11 into 3.2 GLUT for Win32. New code + structure allows for EASY merging! + + o In Win32, the parent gets the right to set the cursor of + any of its children. Therefore, a child windows cursor + will 'blink' between its cursor and its parent. + x Fixed this by checking whether the cursor is in a child + window or not. + + (Feb 28 '97) + o On initial bringup apps are getting 2 display callbacks. + x Fixed by the Fev 28 re-write. + + o Some multiple window (not subwindow) functionality is messed up. + See the sphere.exe program. + x Fixed by the Feb 28 re-write. + + o GLUT for Win32 supports color index mode ONLY in a paletted + display mode (i.e., 256 or 16 color mode). + x Fixed this in the re-write. If you can get a color index + visual (pixel format) you can use color index mode. + + (Feb 28 '97) + o Quite a few bugs (and incompatibilities) were being caused + by the structure that I used in the previous port of GLUT. + Therefore I decided that it would be best to "get back to + the roots". I re-implemented most of glut trying to stick + with the structure layed out by Mark. The result is a much + more stable version that passes ALL (!) (except overlay) + the tests provided by Mark. In addition, this new + structure will allow future enhancements by Mark to be + integrated much more quickly into the Win32 version. Also, + I'm now ordering the bugs in reverse, so that the most + recently fixed appear at the top of the list. + + (9/8/96) + o Changed the glutGetModifiers code to produce an error if not + called in the core input callbacks. + + (9/11/96) + o If the alt key is pressed with more than one other modifier key + it acts as if it is stuck -- it stays selected until pressed + and released again. + x Fixed. + + (9/12/96) + o When a submenu is attached to a menu, sometimes a GPF occurs. + Fixed. Needed to set the submenu before referencing it's members. + + o Kenny: Also, one little problem, I attached the menu to the + right-button, but when the left-button is pressed I detach + it to give the right-button new meaning; if I pop-up the menu and I + don't want to select anything, like most users, I click off of the + menu to make it disappear. When I do this, I get a GLUT error and + the program terminates because I am altering the menu attachment + from within the button press while the menu is active. + x Fixed. Needed to finish the menu when the user presses the button, + not just when a button is released. + + o GLUT for Win32 emulates a middle mouse button by checking if + both mouse buttons are down. This causes a lot of problems with + the menu and other multiple mouse button things. + x Fixed. No more middle mouse button emulation. Perhaps it would + be a good idea to emulate the middle mouse button (if not present) + with a key? + + (9/15/96) + o Added code to accept a user defined icon. If no icon is provided, + a default icon is loaded. + + (9/19/96) + o Shane: Command line options seem to be screwed up. (9/13) + x Fixed. The geometry command line was broken, and so was the + gldebug command line. + + o Fixed a bug in the default glut reshape. It was looking for the + parent of the current window and GPF'ing if there wasn't a parent. + Put in a check for a parent, and if none is there, use the + child. + + o Idle function sucks up all processor cycles. (9/8/96) + x I don't know if this is avoidable. If you have a tight rendering + loop, it may be that the processor time is going to be sucked up + no matter what. You can add a sleep() to the end of your render + loop if you would like to yeild to other processes and you don't + care too much about the speed of your rendering loop. If you have + Hardware that supports OpenGL (like a 3Dpro card, or GLint card) + then this should be less of a problem, since it won't be rendering + in software. (9/11/96) + + o If a window is fully obscured by another window, the visibility + callback is NOT called. As far as I can tell, this is a limitation + of the Win32 api, but a workaround is being searched for. (9/8/96) + x Limitation of the Win32 API + + o Fixed the entry functions. They only work if the keyboard focus + changes. Therefore, in most Win32 systems, the mouse must be + pressed outside of the window to get a GLUT_LEFT message and + then pressed inside the window for a GLUT_ENTERED message. + + o Alt modifier key doesn't work with keyboard callback. (9/8/96) + x Probably okay, because the glut spec says that these keys can + be intercepted by the system (which the alt key is...) (9/11/96) + + (11/17/96) + o glutRemoveMenuItem() not working properly. + x Thanks to Gary (grc@maple.civeng.rutgers.edu) for the fix to + this one. + + o Timer functions are messed up. + x Thanks to Joseph Galbraith for the fix to this one. + + (12/9/96) + o One (minor) difference came up between the X version of glut + and the nt one which you should know about. It is not a new + problem, and it concerns co-ords returned to the pointer + callbacks. (glutMotionFunc, glutMouseFunc) + Under X, you get co-ords in the range 0 +/- 2^15, under NT + you get 0..2^16. This is only really a problem when moving + above or to the left of the window. + eg dragging one pixel ABOVE the window will give :- + under x11 : y = -1 + under nt : y = 2^16 -1 + x Put in fix provided by Shane Clauson. + + (12/17/96) + o Idle functions not working properly for multiple windows. + x Fixed this by posting an idle message to every window in the + window list when idle. + + (12/18/96) + o glutSetCursor() was misbehaving (lthomas@cco.caltech.edu). + x Win32 requires that the hCursor member of the window class + be set to NULL when the class is registered or whenever the + mouse is moved, the original cursor is replaced (go + figure!). Now sets the cursor whenever a WM_MOUSEMOVE message + is received, because the WM_SETCURSOR event resets the cursor + even when in the decoration area. + + o Geometry is not being handled quite right. The numbers don't + take into account the window decorations. That is, if I say + make a window 100x100, then the WHOLE window (not just the + client area) is 100x100. Therefore, the client (opengl) area + is smaller than 100x100. (9/8/96) + x Fixed. Added code to subtract the decoration size on glutGet() + and add the decoration size on glutReshapeWindow(). + + o Multiple glutPostRedisplay() calls are NOT being combined. + To get round the "coalesce" problem on glutPostRedisplay, + the easiest solution is to roll-your-own coalesce by + keeping a global "dirty" flag in the app (eg replace all + calls to glutPostRedisplay with image_dirty=TRUE;), and to + handle image_dirty with a single glutPostRedisplay in the + idle callback when required. (erk - but increases + performance for my particular app (a rendering engine on + the end of a pipleine with a stream of graphics updates) by + a couple of orders of magnitude ! ) (9/8/96) + x Added code to coalesce redisplays. Every idle cycle, a + check is made to see which windows need redisplay, if they + need it, a redisplay is posted. The glutPostRedisplay() + call is just a stub that sets a flag. + + +THANKS: + + Special thanks to the following people for extensive testing, + suggestions, fixes and help: + + Alexander Stohr + Shane Clauson + Kenny Hoff + Richard Readings + Paul McQuesten + Philip Winston + JaeWoo Ahn + Joseph Galbraith + Paula Higgins + Sam Fortin + Chris Vale + Bill Mitchell + + and of course, the original author of GLUT: + Mark Kilgard. + + and many others... + + +COPYRIGHT: + +The OpenGL Utility Toolkit distribution for Win32 (Windows NT & +Windows 95) contains source code modified from the original source +code for GLUT version 3.3 which was developed by Mark J. Kilgard. The +original source code for GLUT is Copyright 1997 by Mark J. Kilgard. +GLUT for Win32 is Copyright 1997 by Nate Robins and is not in the +public domain, but it is freely distributable without licensing fees. +It is provided without guarantee or warrantee expressed or implied. +It was ported with the permission of Mark J. Kilgard by Nate Robins. + +THIS SOURCE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +OpenGL (R) is a registered trademark of Silicon Graphics, Inc. diff --git a/scripts/IFCImporter/entitylist.txt b/scripts/IFCImporter/entitylist.txt index 3c7a9d7eb..14b05ca3e 100644 --- a/scripts/IFCImporter/entitylist.txt +++ b/scripts/IFCImporter/entitylist.txt @@ -1,111 +1,111 @@ -# ============================================================================== -# List of IFC structures needed by Assimp -# ============================================================================== -# use genentitylist.sh to update this list - -# This machine-generated list is not complete, it lacks many intermediate -# classes in the inheritance hierarchy. Those are magically augmented by the -# code generator. Also, the names of all used entities need to be present -# in the source code for this to work. - -IfcAnnotation -IfcArbitraryClosedProfileDef -IfcArbitraryOpenProfileDef -IfcArbitraryProfileDefWithVoids -IfcAxis1Placement -IfcAxis2Placement -IfcAxis2Placement2D -IfcAxis2Placement3D -IfcBooleanClippingResult -IfcBooleanResult -IfcBoundedCurve -IfcBoundingBox -IfcBSplineCurve -IfcBuilding -IfcCartesianPoint -IfcCartesianTransformationOperator -IfcCartesianTransformationOperator3D -IfcCartesianTransformationOperator3DnonUniform -IfcCircle -IfcCircleHollowProfileDef -IfcCircleProfileDef -IfcClosedShell -IfcColourOrFactor -IfcColourRgb -IfcCompositeCurve -IfcCompositeCurveSegment -IfcConic -IfcConnectedFaceSet -IfcConversionBasedUnit -IfcCurve -IfcDirection -IfcDoor -IfcEllipse -IfcExtrudedAreaSolid -IfcFace -IfcFaceBasedSurfaceModel -IfcFaceBound -IfcFaceOuterBound -IfcFeatureElementSubtraction -IfcGeometricRepresentationContext -IfcGeometricRepresentationItem -IfcHalfSpaceSolid -IfcLine -IfcLocalPlacement -IfcManifoldSolidBrep -IfcMappedItem -IfcMeasureWithUnit -IfcNamedUnit -IfcObjectDefinition -IfcObjectPlacement -IfcOpeningElement -IfcParameterizedProfileDef -IfcPlane -IfcPolygonalBoundedHalfSpace -IfcPolyline -IfcPolyLoop -IfcPresentationStyleAssignment -IfcPresentationStyleSelect -IfcProduct -IfcProductRepresentation -IfcProfileDef -IfcProject -IfcRectangleProfileDef -IfcRelAggregates -IfcRelContainedInSpatialStructure -IfcRelFillsElement -IfcRelVoidsElement -IfcRepresentation -IfcRepresentationContext -IfcRepresentationItem -IfcRepresentationMap -IfcRevolvedAreaSolid -IfcShell -IfcShellBasedSurfaceModel -IfcSite -IfcSIUnit -IfcSomething -IfcSpace -IfcSpatialStructureElement -IfcSpatialStructureElements -IfcStyledItem -IfcSurfaceStyle -IfcSurfaceStyleElementSelect -IfcSurfaceStyleRendering -IfcSurfaceStyleShading -IfcSurfaceStyleWithTextures -IfcSweptAreaSolid -IfcSweptDiskSolid -IfcTopologicalRepresentationItem -IfcTrimmedCurve -IfcUnit -IfcUnitAssignment -IfcVector -IfcIShapeProfileDef -IfcPropertyListValue -IfcRelDefinesByProperties -IfcPropertySet -IfcPropertySingleValue -IfcProperty -IfcComplexProperty -IfcElementQuantity +# ============================================================================== +# List of IFC structures needed by Assimp +# ============================================================================== +# use genentitylist.sh to update this list + +# This machine-generated list is not complete, it lacks many intermediate +# classes in the inheritance hierarchy. Those are magically augmented by the +# code generator. Also, the names of all used entities need to be present +# in the source code for this to work. + +IfcAnnotation +IfcArbitraryClosedProfileDef +IfcArbitraryOpenProfileDef +IfcArbitraryProfileDefWithVoids +IfcAxis1Placement +IfcAxis2Placement +IfcAxis2Placement2D +IfcAxis2Placement3D +IfcBooleanClippingResult +IfcBooleanResult +IfcBoundedCurve +IfcBoundingBox +IfcBSplineCurve +IfcBuilding +IfcCartesianPoint +IfcCartesianTransformationOperator +IfcCartesianTransformationOperator3D +IfcCartesianTransformationOperator3DnonUniform +IfcCircle +IfcCircleHollowProfileDef +IfcCircleProfileDef +IfcClosedShell +IfcColourOrFactor +IfcColourRgb +IfcCompositeCurve +IfcCompositeCurveSegment +IfcConic +IfcConnectedFaceSet +IfcConversionBasedUnit +IfcCurve +IfcDirection +IfcDoor +IfcEllipse +IfcExtrudedAreaSolid +IfcFace +IfcFaceBasedSurfaceModel +IfcFaceBound +IfcFaceOuterBound +IfcFeatureElementSubtraction +IfcGeometricRepresentationContext +IfcGeometricRepresentationItem +IfcHalfSpaceSolid +IfcLine +IfcLocalPlacement +IfcManifoldSolidBrep +IfcMappedItem +IfcMeasureWithUnit +IfcNamedUnit +IfcObjectDefinition +IfcObjectPlacement +IfcOpeningElement +IfcParameterizedProfileDef +IfcPlane +IfcPolygonalBoundedHalfSpace +IfcPolyline +IfcPolyLoop +IfcPresentationStyleAssignment +IfcPresentationStyleSelect +IfcProduct +IfcProductRepresentation +IfcProfileDef +IfcProject +IfcRectangleProfileDef +IfcRelAggregates +IfcRelContainedInSpatialStructure +IfcRelFillsElement +IfcRelVoidsElement +IfcRepresentation +IfcRepresentationContext +IfcRepresentationItem +IfcRepresentationMap +IfcRevolvedAreaSolid +IfcShell +IfcShellBasedSurfaceModel +IfcSite +IfcSIUnit +IfcSomething +IfcSpace +IfcSpatialStructureElement +IfcSpatialStructureElements +IfcStyledItem +IfcSurfaceStyle +IfcSurfaceStyleElementSelect +IfcSurfaceStyleRendering +IfcSurfaceStyleShading +IfcSurfaceStyleWithTextures +IfcSweptAreaSolid +IfcSweptDiskSolid +IfcTopologicalRepresentationItem +IfcTrimmedCurve +IfcUnit +IfcUnitAssignment +IfcVector +IfcIShapeProfileDef +IfcPropertyListValue +IfcRelDefinesByProperties +IfcPropertySet +IfcPropertySingleValue +IfcProperty +IfcComplexProperty +IfcElementQuantity diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a93bcf91f..d3bd490e8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,6 +24,7 @@ SET( TEST_SRCS unit/utGenNormals.cpp unit/utImporter.cpp unit/utImproveCacheLocality.cpp + unit/utIOSystem.cpp unit/utJoinVertices.cpp unit/utLimitBoneWeights.cpp unit/utMaterialSystem.cpp diff --git a/test/models-nonbsd/3D/mar_rifle.source.txt b/test/models-nonbsd/3D/mar_rifle.source.txt index ac8721d26..c0cd5fe6d 100644 --- a/test/models-nonbsd/3D/mar_rifle.source.txt +++ b/test/models-nonbsd/3D/mar_rifle.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008. -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008. +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/cart_wheel.source.txt b/test/models-nonbsd/3DS/cart_wheel.source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/3DS/cart_wheel.source.txt +++ b/test/models-nonbsd/3DS/cart_wheel.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/jeep1.3ds.readme.txt b/test/models-nonbsd/3DS/jeep1.3ds.readme.txt index 14b0bd9eb..d17d5e0e9 100644 --- a/test/models-nonbsd/3DS/jeep1.3ds.readme.txt +++ b/test/models-nonbsd/3DS/jeep1.3ds.readme.txt @@ -1,15 +1,15 @@ -Jeep designed, modelled and skinned by me, Psionic - -FREE for use however you like, credits are appreciated!!! - -It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. - -I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! - -Check out more of my work at:- - -http://xu1productions.com/3dstudio/index.html - 3D Game Resources - -http://www.psionicdesign.com - My Main 2D/3D Digital Art site - +Jeep designed, modelled and skinned by me, Psionic + +FREE for use however you like, credits are appreciated!!! + +It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. + +I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! + +Check out more of my work at:- + +http://xu1productions.com/3dstudio/index.html - 3D Game Resources + +http://www.psionicdesign.com - My Main 2D/3D Digital Art site + Psionic 2002 \ No newline at end of file diff --git a/test/models-nonbsd/3DS/mar_rifle.source.txt b/test/models-nonbsd/3DS/mar_rifle.source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/3DS/mar_rifle.source.txt +++ b/test/models-nonbsd/3DS/mar_rifle.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/mp5_sil.source.txt b/test/models-nonbsd/3DS/mp5_sil.source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/3DS/mp5_sil.source.txt +++ b/test/models-nonbsd/3DS/mp5_sil.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/pyramob.3ds.readme.txt b/test/models-nonbsd/3DS/pyramob.3ds.readme.txt index 7f6cf0361..bf1858410 100644 --- a/test/models-nonbsd/3DS/pyramob.3ds.readme.txt +++ b/test/models-nonbsd/3DS/pyramob.3ds.readme.txt @@ -1,12 +1,12 @@ -hello! - -fell free to use the object...so do what U want! -& sent me your pictures...:-) -for commercial use, contact me! - -http://www.elektrobar.com/lux/ - -or mail to: -lux@elektrobar.com - +hello! + +fell free to use the object...so do what U want! +& sent me your pictures...:-) +for commercial use, contact me! + +http://www.elektrobar.com/lux/ + +or mail to: +lux@elektrobar.com + have fun.....VIRLUX \ No newline at end of file diff --git a/test/models-nonbsd/ASE/Rifle.source.txt b/test/models-nonbsd/ASE/Rifle.source.txt index 914c69466..04d40a85d 100644 --- a/test/models-nonbsd/ASE/Rifle.source.txt +++ b/test/models-nonbsd/ASE/Rifle.source.txt @@ -1,25 +1,25 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + + +INFO +==== + CONVERTED FROM 3DS TO ASE WITH AC3D \ No newline at end of file diff --git a/test/models-nonbsd/ASE/Rifle2.source.txt b/test/models-nonbsd/ASE/Rifle2.source.txt index f0dda0b20..2072ddf13 100644 --- a/test/models-nonbsd/ASE/Rifle2.source.txt +++ b/test/models-nonbsd/ASE/Rifle2.source.txt @@ -1,24 +1,24 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + +INFO +==== + CONVERTED FROM 3DS TO ASE WITH AC3D \ No newline at end of file diff --git a/test/models-nonbsd/B3D/dwarf.source.txt b/test/models-nonbsd/B3D/dwarf.source.txt index c062dcabf..1a0040fba 100644 --- a/test/models-nonbsd/B3D/dwarf.source.txt +++ b/test/models-nonbsd/B3D/dwarf.source.txt @@ -1,51 +1,51 @@ -Dwarf lowpoly model Pack -Copyright 2004, Psionic Design -e-mail: psionic@blueyonder.co.uk -Used with permission. - - -INSTALLATION INSTRUCTIONS: - -To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! - - - -USAGE INFORMATION: - -Each zip contains the models, textures and animation info for that particular format! - -Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use - -Credits to me "Psionic" are really appreciated but are not essential ;-) - -Any questions, screenshots of him in use etc drop by my site or email me at:- - -website: http://www.psionic3d.co.uk -email: psionic@blueyonder.co.uk - - - - -WHAT'S INCLUDED IN THE ZIP: - -ReadMe.txt - This file -b3d.zip - Blitz 3D Format models and textures -ms3d.zip - Milkshape 3D Format models and textures -x.zip - DarkBasic Direct X 8 Format models and textures - - - -RESTRICTIONS: - -This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- - -**You may not sell/re-sell this model pack or claim it as your own. -***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. - - -Psi -http://www.psionic3d.co.uk - - - - +Dwarf lowpoly model Pack +Copyright 2004, Psionic Design +e-mail: psionic@blueyonder.co.uk +Used with permission. + + +INSTALLATION INSTRUCTIONS: + +To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! + + + +USAGE INFORMATION: + +Each zip contains the models, textures and animation info for that particular format! + +Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use + +Credits to me "Psionic" are really appreciated but are not essential ;-) + +Any questions, screenshots of him in use etc drop by my site or email me at:- + +website: http://www.psionic3d.co.uk +email: psionic@blueyonder.co.uk + + + + +WHAT'S INCLUDED IN THE ZIP: + +ReadMe.txt - This file +b3d.zip - Blitz 3D Format models and textures +ms3d.zip - Milkshape 3D Format models and textures +x.zip - DarkBasic Direct X 8 Format models and textures + + + +RESTRICTIONS: + +This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- + +**You may not sell/re-sell this model pack or claim it as your own. +***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. + + +Psi +http://www.psionic3d.co.uk + + + + diff --git a/test/models-nonbsd/B3D/turtle.source.txt b/test/models-nonbsd/B3D/turtle.source.txt index 187fa95a7..fab387bdc 100644 --- a/test/models-nonbsd/B3D/turtle.source.txt +++ b/test/models-nonbsd/B3D/turtle.source.txt @@ -1,11 +1,11 @@ -turtle1.b3d -Copyright 2004, Psionic Design -e-mail: psionic@blueyonder.co.uk -Used with permission. - -RESTRICTIONS: - -This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- - -**You may not sell/re-sell this model pack or claim it as your own. +turtle1.b3d +Copyright 2004, Psionic Design +e-mail: psionic@blueyonder.co.uk +Used with permission. + +RESTRICTIONS: + +This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- + +**You may not sell/re-sell this model pack or claim it as your own. ***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. \ No newline at end of file diff --git a/test/models-nonbsd/BLEND/bob.source.txt b/test/models-nonbsd/BLEND/bob.source.txt index ac86757d1..592693550 100644 --- a/test/models-nonbsd/BLEND/bob.source.txt +++ b/test/models-nonbsd/BLEND/bob.source.txt @@ -1,31 +1,31 @@ - ----------------------------------------------------------------------------------------------- -TITLE : Bob, MD5 character source file -AUTHOR : Ken Beyer (kat) -EMAIL ADDRESS : info@katsbits.com -HOMEPAGE URL : http://www.katsbits.com - - -MODEL NAME/s -Zip file contains *.blend source file and TGA texture assets for MD5 format testing. -Files and media are provided "as is" without any explicit or implied warranty of fuctionality. - - -DISTRIBUTION -Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. -Commercial use is permitted with written licensed permission. ----------------------------------------------------------------------------------------------- - -Files: - - Bob.md5mesh - - Bob.md5anim - - Bob.blend - - ./*.png - -Changes: - - converted all tga's to png, updated .blend and .md5mesh accordingly - - removed absolute texture paths from the md5mesh file - - minor downscaling of all textures to fit in less bytes - - - + +---------------------------------------------------------------------------------------------- +TITLE : Bob, MD5 character source file +AUTHOR : Ken Beyer (kat) +EMAIL ADDRESS : info@katsbits.com +HOMEPAGE URL : http://www.katsbits.com + + +MODEL NAME/s +Zip file contains *.blend source file and TGA texture assets for MD5 format testing. +Files and media are provided "as is" without any explicit or implied warranty of fuctionality. + + +DISTRIBUTION +Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. +Commercial use is permitted with written licensed permission. +---------------------------------------------------------------------------------------------- + +Files: + - Bob.md5mesh + - Bob.md5anim + - Bob.blend + - ./*.png + +Changes: + - converted all tga's to png, updated .blend and .md5mesh accordingly + - removed absolute texture paths from the md5mesh file + - minor downscaling of all textures to fit in less bytes + + + diff --git a/test/models-nonbsd/DXF/rifle.source.txt b/test/models-nonbsd/DXF/rifle.source.txt index f37e2cf8d..3e88f009f 100644 --- a/test/models-nonbsd/DXF/rifle.source.txt +++ b/test/models-nonbsd/DXF/rifle.source.txt @@ -1,23 +1,23 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + +INFO +==== + COnverted from 3ds to DXF with Ac3D \ No newline at end of file diff --git a/test/models-nonbsd/IFC/linklist.txt b/test/models-nonbsd/IFC/linklist.txt index 041435c50..06ad3844b 100644 --- a/test/models-nonbsd/IFC/linklist.txt +++ b/test/models-nonbsd/IFC/linklist.txt @@ -1,4 +1,4 @@ -Good IFC test cases -=================== - +Good IFC test cases +=================== + http://www.iai.fzk.de/www-extern/index.php?id=1135 \ No newline at end of file diff --git a/test/models-nonbsd/IRR/skybox/credits.txt b/test/models-nonbsd/IRR/skybox/credits.txt index 0b2135e88..b2b601392 100644 --- a/test/models-nonbsd/IRR/skybox/credits.txt +++ b/test/models-nonbsd/IRR/skybox/credits.txt @@ -1,11 +1,11 @@ -This skybox is basing on a skydome texture from - -http://mikepan.homeip.net/earth - -Downloaded November 22th, 08 -Distribution note: -"These royalty-free skydome textures work best when applied to a sphere or hemisphere" - - - -Thanks for your great work! +This skybox is basing on a skydome texture from + +http://mikepan.homeip.net/earth + +Downloaded November 22th, 08 +Distribution note: +"These royalty-free skydome textures work best when applied to a sphere or hemisphere" + + + +Thanks for your great work! diff --git a/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt b/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt index 80dc1df4e..bb07f8e24 100644 --- a/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt +++ b/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt @@ -1,31 +1,31 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -"These 3d models are contributed by John Hoffman and are based on -characters from a cartoon show called "Jayce and the wheel warriors" -(except the marauder) John's site: http://www3.sympatico.ca/john.hoffman" - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - - -INFO -==== - - -These files belong to the QuickDraw model in the LWS folder - they are referenced +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +"These 3d models are contributed by John Hoffman and are based on +characters from a cartoon show called "Jayce and the wheel warriors" +(except the marauder) John's site: http://www3.sympatico.ca/john.hoffman" + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + + +INFO +==== + + +These files belong to the QuickDraw model in the LWS folder - they are referenced and loaded into the LWS scene. \ No newline at end of file diff --git a/test/models-nonbsd/LWO/LWO2/rifle.source.txt b/test/models-nonbsd/LWO/LWO2/rifle.source.txt index 02680a50a..34576f0ca 100644 --- a/test/models-nonbsd/LWO/LWO2/rifle.source.txt +++ b/test/models-nonbsd/LWO/LWO2/rifle.source.txt @@ -1,24 +1,24 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + +INFO +==== + CONVERTED FROM 3DS TO LWO2 WITH AC3D \ No newline at end of file diff --git a/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt b/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt index a40f330e5..e0c7d0f7c 100644 --- a/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt +++ b/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt @@ -1,15 +1,15 @@ -From http://telias.free.fr - - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, lightwave and md2 format. Also a great collection of textures to use in your favorite modelling and rendering program. -All the content is free for any use. -In the future more 3d formats will be added and some other sections such as wallpapers, 3d screensavers, 3d coding source code and tutorials. -" - - -CHANGES: +From http://telias.free.fr + + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, lightwave and md2 format. Also a great collection of textures to use in your favorite modelling and rendering program. +All the content is free for any use. +In the future more 3d formats will be added and some other sections such as wallpapers, 3d screensavers, 3d coding source code and tutorials. +" + + +CHANGES: Paths have been modified \ No newline at end of file diff --git a/test/models-nonbsd/MD2/source.txt b/test/models-nonbsd/MD2/source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/MD2/source.txt +++ b/test/models-nonbsd/MD2/source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt b/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt index 9b56b97c4..e0a978ee0 100644 --- a/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt +++ b/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt @@ -1,26 +1,26 @@ -------------------------------------------------------------------------- - -TITLE : kt_kubalwagon -AUTHOR : ken 'kat' beyer -EMAIL ADDRESS : cpdt@telinco.co.uk -HOMEPAGE URL : http://www.quake3bits.co.uk -NUMBER OF MODELS : 1 -SHADER SCRIPTS : yes - included - ------------------- -* MODEL NAME/s * -[model details below] -european_fnt_v2.md3 - -euro_rnt_2.tga (alpha'd steering wheel) -european_fnt.tga - - ------------------- - -CREDITS -ID software, eskimo roll, EMSIPE, QkenneyQ -DISTRIBUTION -as long as this readme is included...! - +------------------------------------------------------------------------- + +TITLE : kt_kubalwagon +AUTHOR : ken 'kat' beyer +EMAIL ADDRESS : cpdt@telinco.co.uk +HOMEPAGE URL : http://www.quake3bits.co.uk +NUMBER OF MODELS : 1 +SHADER SCRIPTS : yes - included + +------------------ +* MODEL NAME/s * +[model details below] +european_fnt_v2.md3 + +euro_rnt_2.tga (alpha'd steering wheel) +european_fnt.tga + + +------------------ + +CREDITS +ID software, eskimo roll, EMSIPE, QkenneyQ +DISTRIBUTION +as long as this readme is included...! + -------------------------------------------------------------------------- \ No newline at end of file diff --git a/test/models-nonbsd/MD3/readme_water.txt b/test/models-nonbsd/MD3/readme_water.txt index d80e7eb0e..cdc318ff8 100644 --- a/test/models-nonbsd/MD3/readme_water.txt +++ b/test/models-nonbsd/MD3/readme_water.txt @@ -1,26 +1,26 @@ -------------------------------------------------------------------------- - -TITLE : kt_watercan -AUTHOR : ken 'kat' beyer -EMAIL ADDRESS : cpdt@telinco.co.uk -HOMEPAGE URL : http://www.quake3bits.co.uk -NUMBER OF MODELS : 2 -SHADER SCRIPTS : n/a - ------------------- -* MODEL NAME/s * -[model details below] -watercan.md3 -watercan_dmg.md3 (dmg='damaged') - -water_can.tga 256x128 - - ------------------- - -CREDITS -ID software, eskimo roll, EMSIPE, QkenneyQ -DISTRIBUTION -as long as this readme is included...! - +------------------------------------------------------------------------- + +TITLE : kt_watercan +AUTHOR : ken 'kat' beyer +EMAIL ADDRESS : cpdt@telinco.co.uk +HOMEPAGE URL : http://www.quake3bits.co.uk +NUMBER OF MODELS : 2 +SHADER SCRIPTS : n/a + +------------------ +* MODEL NAME/s * +[model details below] +watercan.md3 +watercan_dmg.md3 (dmg='damaged') + +water_can.tga 256x128 + + +------------------ + +CREDITS +ID software, eskimo roll, EMSIPE, QkenneyQ +DISTRIBUTION +as long as this readme is included...! + -------------------------------------------------------------------------- \ No newline at end of file diff --git a/test/models-nonbsd/MD5/BoarMan.source.txt b/test/models-nonbsd/MD5/BoarMan.source.txt index cbba6edf6..50b2dfb53 100644 --- a/test/models-nonbsd/MD5/BoarMan.source.txt +++ b/test/models-nonbsd/MD5/BoarMan.source.txt @@ -1,8 +1,8 @@ - -License: Creative Commons - - Remix - - Share alike - - Attribution Author: zphr (Christian Lenke) - - - + +License: Creative Commons + - Remix + - Share alike + - Attribution Author: zphr (Christian Lenke) + + + diff --git a/test/models-nonbsd/MD5/bob.source.txt b/test/models-nonbsd/MD5/bob.source.txt index ac86757d1..592693550 100644 --- a/test/models-nonbsd/MD5/bob.source.txt +++ b/test/models-nonbsd/MD5/bob.source.txt @@ -1,31 +1,31 @@ - ----------------------------------------------------------------------------------------------- -TITLE : Bob, MD5 character source file -AUTHOR : Ken Beyer (kat) -EMAIL ADDRESS : info@katsbits.com -HOMEPAGE URL : http://www.katsbits.com - - -MODEL NAME/s -Zip file contains *.blend source file and TGA texture assets for MD5 format testing. -Files and media are provided "as is" without any explicit or implied warranty of fuctionality. - - -DISTRIBUTION -Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. -Commercial use is permitted with written licensed permission. ----------------------------------------------------------------------------------------------- - -Files: - - Bob.md5mesh - - Bob.md5anim - - Bob.blend - - ./*.png - -Changes: - - converted all tga's to png, updated .blend and .md5mesh accordingly - - removed absolute texture paths from the md5mesh file - - minor downscaling of all textures to fit in less bytes - - - + +---------------------------------------------------------------------------------------------- +TITLE : Bob, MD5 character source file +AUTHOR : Ken Beyer (kat) +EMAIL ADDRESS : info@katsbits.com +HOMEPAGE URL : http://www.katsbits.com + + +MODEL NAME/s +Zip file contains *.blend source file and TGA texture assets for MD5 format testing. +Files and media are provided "as is" without any explicit or implied warranty of fuctionality. + + +DISTRIBUTION +Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. +Commercial use is permitted with written licensed permission. +---------------------------------------------------------------------------------------------- + +Files: + - Bob.md5mesh + - Bob.md5anim + - Bob.blend + - ./*.png + +Changes: + - converted all tga's to png, updated .blend and .md5mesh accordingly + - removed absolute texture paths from the md5mesh file + - minor downscaling of all textures to fit in less bytes + + + diff --git a/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt b/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt index 93afb7cb1..2febb0583 100644 --- a/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt +++ b/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt @@ -1,73 +1,73 @@ -Title : G.I.Joe Skins -Filename : joemodel.zip -Version : 1 -Date : 11/05/97 -Author : Kenneth Whelan -Email : JWHELAN@pop.prodigy.net -Credits : id software, Larry Hama, Steven Polge, and Rene Post for making Quake ME - - - -Build time: ??? Time??? - -Type of Mod ------------ -Quake C : no -Sound : no -MDL : Yes - - -Format of QuakeC (if a Quake C Mod) ------------------------------------ -unified diff : no -context diff : no -.qc files : no -progs.dat : no - - -Description of the Modification -------------------------------- - -This is a new player.mdl for quake. It's main use is for bots. The Skins are Snake Eyes v4, Duke v3, Low-Light, -Storm Shadow v2, Shockwave, Repeater, Gung-Ho, Shipwreck, Dusty v3, and -Tunnel Rat v2. - - - -Known bugs -None that I know of. - -How to Install the Modification -------------------------------- - -First back up the current player.mdl(copy player.mdl player.bak). Just put -it in the progs dir in the hack your using, if any. - -Technical Details ------------------ - -can't think of any - - -Author Information ------------------- - -This is my first publicly distributed quake graphic change. -I did it to get away from the stress of school. - - -Copyright and Distribution Permissions --------------------------------------- - -You may distribute this Quake modification in any electronic format as long as - all the files in this archive remain intact and unmodified and are distributed - together. - - -Availability ------------- - -This modification is available from the following places: - - http://www.yojoe.com/ - +Title : G.I.Joe Skins +Filename : joemodel.zip +Version : 1 +Date : 11/05/97 +Author : Kenneth Whelan +Email : JWHELAN@pop.prodigy.net +Credits : id software, Larry Hama, Steven Polge, and Rene Post for making Quake ME + + + +Build time: ??? Time??? + +Type of Mod +----------- +Quake C : no +Sound : no +MDL : Yes + + +Format of QuakeC (if a Quake C Mod) +----------------------------------- +unified diff : no +context diff : no +.qc files : no +progs.dat : no + + +Description of the Modification +------------------------------- + +This is a new player.mdl for quake. It's main use is for bots. The Skins are Snake Eyes v4, Duke v3, Low-Light, +Storm Shadow v2, Shockwave, Repeater, Gung-Ho, Shipwreck, Dusty v3, and +Tunnel Rat v2. + + + +Known bugs +None that I know of. + +How to Install the Modification +------------------------------- + +First back up the current player.mdl(copy player.mdl player.bak). Just put +it in the progs dir in the hack your using, if any. + +Technical Details +----------------- + +can't think of any + + +Author Information +------------------ + +This is my first publicly distributed quake graphic change. +I did it to get away from the stress of school. + + +Copyright and Distribution Permissions +-------------------------------------- + +You may distribute this Quake modification in any electronic format as long as + all the files in this archive remain intact and unmodified and are distributed + together. + + +Availability +------------ + +This modification is available from the following places: + + http://www.yojoe.com/ + diff --git a/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt b/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt index fb8d5304b..c07c2f126 100644 --- a/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt +++ b/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt @@ -1,33 +1,33 @@ -Stegosaur Model -from the Free Models Project -www.oz.net/~simitar/model.html - - -June 3, 1997 - -created by Sirius (Dillon Aumiller) -E-mail: sirius25@hotmail.com - - -June 5, 1997 - -modified by The Serpent Lord (Seth Galbraith) -E-mail: sgalbrai@linknet.kitsap.lib.wa.us -WWW: www.oz.net/~simitar - - -This model can be used or modified for any purpose -as long as this text document is included with it -and all modellers listed in this document are -listed wherever credits are appropriate for that -purpose. - - -Help Wanted: - -The Free Models Project can use help with -models and in other areas, such as legal boilerplate -for models. - -WWW: www.oz.net/~simitar/model.html -E-mail: sgalbrai@linknet.kitsap.lib.wa.us +Stegosaur Model +from the Free Models Project +www.oz.net/~simitar/model.html + + +June 3, 1997 + +created by Sirius (Dillon Aumiller) +E-mail: sirius25@hotmail.com + + +June 5, 1997 + +modified by The Serpent Lord (Seth Galbraith) +E-mail: sgalbrai@linknet.kitsap.lib.wa.us +WWW: www.oz.net/~simitar + + +This model can be used or modified for any purpose +as long as this text document is included with it +and all modellers listed in this document are +listed wherever credits are appropriate for that +purpose. + + +Help Wanted: + +The Free Models Project can use help with +models and in other areas, such as legal boilerplate +for models. + +WWW: www.oz.net/~simitar/model.html +E-mail: sgalbrai@linknet.kitsap.lib.wa.us diff --git a/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt b/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt index a263d9c8b..dc0149b01 100644 --- a/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt +++ b/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt @@ -1,33 +1,33 @@ - -+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+) - -teckmechbot animated .mdl - -This model was created for the FMP, because I believe -that the FMP is a great concept !! - -There is some movement in the model. -The legs can be animated for walking, stomping, or running -around ! -Ok, it's my first model, so I will work on less polygony -in the future ;-) - - -Created By: Curiel7 -Contact: ebuy@optelnow.net (E-MAIL) -Date Created: 7/07/2000 -====================================================== - -This model can be used or modified for any purpose -as long as this text document is included with it -and all modelers listed in this document are -listed wherever credits are appropriate for that -purpose. - - -The Free Models Project can use your help with -game-oriented models and other areas - -WWW: http://www.planetquake.com/simitar -E-mail: sgalbrai@linknet.kitsap.lib.wa.us - + ++)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+) + +teckmechbot animated .mdl + +This model was created for the FMP, because I believe +that the FMP is a great concept !! + +There is some movement in the model. +The legs can be animated for walking, stomping, or running +around ! +Ok, it's my first model, so I will work on less polygony +in the future ;-) + + +Created By: Curiel7 +Contact: ebuy@optelnow.net (E-MAIL) +Date Created: 7/07/2000 +====================================================== + +This model can be used or modified for any purpose +as long as this text document is included with it +and all modelers listed in this document are +listed wherever credits are appropriate for that +purpose. + + +The Free Models Project can use your help with +game-oriented models and other areas + +WWW: http://www.planetquake.com/simitar +E-mail: sgalbrai@linknet.kitsap.lib.wa.us + diff --git a/test/models-nonbsd/NFF/NFFSense8/credits.txt b/test/models-nonbsd/NFF/NFFSense8/credits.txt index 555721a7d..ff169151d 100644 --- a/test/models-nonbsd/NFF/NFFSense8/credits.txt +++ b/test/models-nonbsd/NFF/NFFSense8/credits.txt @@ -1,4 +1,4 @@ -teapot.nff, home4.nff - http://www.martinreddy.net/ukvrsig/wtk.html - -cokecan.nff -www.vrupl.evl.uic.edu/Eng591_Pages/cokecan.nff +teapot.nff, home4.nff - http://www.martinreddy.net/ukvrsig/wtk.html + +cokecan.nff -www.vrupl.evl.uic.edu/Eng591_Pages/cokecan.nff TODO: License status to be confirmed \ No newline at end of file diff --git a/test/models-nonbsd/OBJ/rifle.source.txt b/test/models-nonbsd/OBJ/rifle.source.txt index 842a9cfc0..b09dcda8c 100644 --- a/test/models-nonbsd/OBJ/rifle.source.txt +++ b/test/models-nonbsd/OBJ/rifle.source.txt @@ -1,27 +1,27 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notices found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - -" -'Free the models' is a site dedicated to provide free content for 3d applications and 3d/game engines. The license of the content is that what you download from here is one step away from public domain. So, everything you download from here is free for any use EXCEPT it cannot be included in another free web or cd collection and it cannot be sold. Otherwise you can use it in your commercial game, 3d application or render work. You don't have to provide credit but It would be nice if you do. -" - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notices found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + +" +'Free the models' is a site dedicated to provide free content for 3d applications and 3d/game engines. The license of the content is that what you download from here is one step away from public domain. So, everything you download from here is free for any use EXCEPT it cannot be included in another free web or cd collection and it cannot be sold. Otherwise you can use it in your commercial game, 3d application or render work. You don't have to provide credit but It would be nice if you do. +" + +INFO +==== + Converted from 3DS to OBJ with AC3D \ No newline at end of file diff --git a/test/models-nonbsd/OBJ/segment.source.txt b/test/models-nonbsd/OBJ/segment.source.txt index 35e13588f..978d72d26 100644 --- a/test/models-nonbsd/OBJ/segment.source.txt +++ b/test/models-nonbsd/OBJ/segment.source.txt @@ -1,4 +1,4 @@ -Obj exported from Blender - -http://toychest.in.tum.de/wiki/projects:kuka_lwr +Obj exported from Blender + +http://toychest.in.tum.de/wiki/projects:kuka_lwr License: Creative-Commons-by-Attribution-3.0 \ No newline at end of file diff --git a/test/models-nonbsd/README.txt b/test/models-nonbsd/README.txt index a6842987b..8b244d2aa 100644 --- a/test/models-nonbsd/README.txt +++ b/test/models-nonbsd/README.txt @@ -1,3 +1,3 @@ -These models are not generally redistributable under the terms of Assimp's BSD license. Usually, an additional requirement on the use of the data is imposed (i.e. no commercial use, need credits, some creative commons variants, ...). - +These models are not generally redistributable under the terms of Assimp's BSD license. Usually, an additional requirement on the use of the data is imposed (i.e. no commercial use, need credits, some creative commons variants, ...). + So, if you re-package Assimp for use in a 'clean' OSS package, consider removing this directory. \ No newline at end of file diff --git a/test/models-nonbsd/X/dwarf-Read-Me.txt b/test/models-nonbsd/X/dwarf-Read-Me.txt index ad1583752..ecf775d0b 100644 --- a/test/models-nonbsd/X/dwarf-Read-Me.txt +++ b/test/models-nonbsd/X/dwarf-Read-Me.txt @@ -1,51 +1,51 @@ -Dwarf lowpoly model Pack -Copyright 2004, Psionic Design -e-mail: psionic@blueyonder.co.uk - - - -INSTALLATION INSTRUCTIONS: - -To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! - - - -USAGE INFORMATION: - -Each zip contains the models, textures and animation info for that particular format! - -Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use - -Credits to me "Psionic" are really appreciated but are not essential ;-) - -Any questions, screenshots of him in use etc drop by my site or email me at:- - -website: http://www.psionic3d.co.uk -email: psionic@blueyonder.co.uk - - - - -WHAT'S INCLUDED IN THE ZIP: - -ReadMe.txt - This file -b3d.zip - Blitz 3D Format models and textures -ms3d.zip - Milkshape 3D Format models and textures -x.zip - DarkBasic Direct X 8 Format models and textures - - - -RESTRICTIONS: - -This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- - -**You may not sell/re-sell this model pack or claim it as your own. -***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. - - -Psi -http://www.psionic3d.co.uk - - - - +Dwarf lowpoly model Pack +Copyright 2004, Psionic Design +e-mail: psionic@blueyonder.co.uk + + + +INSTALLATION INSTRUCTIONS: + +To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! + + + +USAGE INFORMATION: + +Each zip contains the models, textures and animation info for that particular format! + +Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use + +Credits to me "Psionic" are really appreciated but are not essential ;-) + +Any questions, screenshots of him in use etc drop by my site or email me at:- + +website: http://www.psionic3d.co.uk +email: psionic@blueyonder.co.uk + + + + +WHAT'S INCLUDED IN THE ZIP: + +ReadMe.txt - This file +b3d.zip - Blitz 3D Format models and textures +ms3d.zip - Milkshape 3D Format models and textures +x.zip - DarkBasic Direct X 8 Format models and textures + + + +RESTRICTIONS: + +This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- + +**You may not sell/re-sell this model pack or claim it as your own. +***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. + + +Psi +http://www.psionic3d.co.uk + + + + diff --git a/test/models/3DS/UVTransformTest/note.txt b/test/models/3DS/UVTransformTest/note.txt index fcb276d28..dc4bd0789 100644 --- a/test/models/3DS/UVTransformTest/note.txt +++ b/test/models/3DS/UVTransformTest/note.txt @@ -1,11 +1,11 @@ -All 'mirror' files are not absolutely correct. That's mainly -because it's difficult convert Max' handling of mirroring to -our's. - -In other words: TO DO, but only if someone REALLY needs it. - -------------------------------------------------------------- - -To see how it should look like - test/ReferenceImages -Note that the viewer has no 'decal' texture mapping mode, so +All 'mirror' files are not absolutely correct. That's mainly +because it's difficult convert Max' handling of mirroring to +our's. + +In other words: TO DO, but only if someone REALLY needs it. + +------------------------------------------------------------- + +To see how it should look like - test/ReferenceImages +Note that the viewer has no 'decal' texture mapping mode, so the usual clamping is used. \ No newline at end of file diff --git a/test/models/ASE/MotionCaptureROM.source.txt b/test/models/ASE/MotionCaptureROM.source.txt index 72542af41..222a3afbb 100644 --- a/test/models/ASE/MotionCaptureROM.source.txt +++ b/test/models/ASE/MotionCaptureROM.source.txt @@ -1,3 +1,3 @@ -"MotionCaptureROM.ase" - Free for any purpose. - +"MotionCaptureROM.ase" - Free for any purpose. + NOTE: The errors in the middle of the animation are caused by problems during recording, it's not an importer issue. \ No newline at end of file diff --git a/test/models/BLEND/HUMAN.source.txt b/test/models/BLEND/HUMAN.source.txt index 4cb20c906..9409b46d3 100644 --- a/test/models/BLEND/HUMAN.source.txt +++ b/test/models/BLEND/HUMAN.source.txt @@ -1,3 +1,3 @@ -HUMAN.blend (c) 2010, Tobias Rittig - +HUMAN.blend (c) 2010, Tobias Rittig + Redistribution and reuse allowed for any purpose, credits appreciated. \ No newline at end of file diff --git a/test/models/BVH/01_nn.bvh.source.txt b/test/models/BVH/01_nn.bvh.source.txt index a68993950..e538020a2 100644 --- a/test/models/BVH/01_nn.bvh.source.txt +++ b/test/models/BVH/01_nn.bvh.source.txt @@ -1,50 +1,50 @@ -http://sites.google.com/a/cgspeed.com/cgspeed/motion-capture/cmu-bvh-conversion - - -ReadmeFirst.txt -================ - - -READMEFIRST v1.00 last update July 20, 2008 by B. Hahne - -This READMEFIRST file accompanies the cgspeed.com "BVH conversion" -release of the Carnegie-Mellon University (CMU) Graphics Lab Motion -Capture Database. See "Where to find stuff" at the bottom of this -file for where to get the BVH conversion and/or the original CMU -dataset. - -The original CMU motion capture database isn't in BVH format - it's -in ASF/AMC format. This BVH conversion release was created by Bruce -Hahne, a hobbyist animator, in the interest of making the data more -available and easily usable by other animators. I presently (2008) -maintain the web site www.cgspeed.com, where this BVH conversion -release will be available or linked. - -The emphasis on this release is to produce BVH files that can rapidly -be used in MotionBuilder for motion retargetting. The files are not -yet particularly Poser-friendly or DazStudio-friendly, due to -incorrect assumptions that those programs have to make about the -underlying joint rotation setup. - - -[...] - - - -USAGE RIGHTS: - -CMU places no restrictions on the use of the original dataset, and I -(Bruce) place no additional restrictions on the use of this particular -BVH conversion. - -Here's the relevant paragraph from mocap.cs.cmu.edu: - - Use this data! This data is free for use in research and commercial - projects worldwide. If you publish results obtained using this data, - we would appreciate it if you would send the citation to your - published paper to jkh+mocap@cs.cmu.edu, and also would add this text - to your acknowledgments section: "The data used in this project was - obtained from mocap.cs.cmu.edu. The database was created with funding - from NSF EIA-0196217." - +http://sites.google.com/a/cgspeed.com/cgspeed/motion-capture/cmu-bvh-conversion + + +ReadmeFirst.txt +================ + + +READMEFIRST v1.00 last update July 20, 2008 by B. Hahne + +This READMEFIRST file accompanies the cgspeed.com "BVH conversion" +release of the Carnegie-Mellon University (CMU) Graphics Lab Motion +Capture Database. See "Where to find stuff" at the bottom of this +file for where to get the BVH conversion and/or the original CMU +dataset. + +The original CMU motion capture database isn't in BVH format - it's +in ASF/AMC format. This BVH conversion release was created by Bruce +Hahne, a hobbyist animator, in the interest of making the data more +available and easily usable by other animators. I presently (2008) +maintain the web site www.cgspeed.com, where this BVH conversion +release will be available or linked. + +The emphasis on this release is to produce BVH files that can rapidly +be used in MotionBuilder for motion retargetting. The files are not +yet particularly Poser-friendly or DazStudio-friendly, due to +incorrect assumptions that those programs have to make about the +underlying joint rotation setup. + + +[...] + + + +USAGE RIGHTS: + +CMU places no restrictions on the use of the original dataset, and I +(Bruce) place no additional restrictions on the use of this particular +BVH conversion. + +Here's the relevant paragraph from mocap.cs.cmu.edu: + + Use this data! This data is free for use in research and commercial + projects worldwide. If you publish results obtained using this data, + we would appreciate it if you would send the citation to your + published paper to jkh+mocap@cs.cmu.edu, and also would add this text + to your acknowledgments section: "The data used in this project was + obtained from mocap.cs.cmu.edu. The database was created with funding + from NSF EIA-0196217." + [...] \ No newline at end of file diff --git a/test/models/Collada/kwxport_test_vcolors.dae.source.txt b/test/models/Collada/kwxport_test_vcolors.dae.source.txt index d173f5a47..94ee48e4a 100644 --- a/test/models/Collada/kwxport_test_vcolors.dae.source.txt +++ b/test/models/Collada/kwxport_test_vcolors.dae.source.txt @@ -1,16 +1,16 @@ -From kwxport -http://www.kwxport.org/ - ->> -The kW Xport plug-in source is released under the MIT license. -Basically, it means "feel free to use it; credit the source; don't sue me -if something goes wrong." ->> - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +From kwxport +http://www.kwxport.org/ + +>> +The kW Xport plug-in source is released under the MIT license. +Basically, it means "feel free to use it; credit the source; don't sue me +if something goes wrong." +>> + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test/models/IRR/warn_dwarf_scaling_is_intended.txt b/test/models/IRR/warn_dwarf_scaling_is_intended.txt index 1fcb03b9a..f651a8643 100644 --- a/test/models/IRR/warn_dwarf_scaling_is_intended.txt +++ b/test/models/IRR/warn_dwarf_scaling_is_intended.txt @@ -1,3 +1,3 @@ -for dawfInCellar_ChildOfCellar & dawfInCellar_SameHierarchy: - -the strange scalings of cellar and dwarf are intended. +for dawfInCellar_ChildOfCellar & dawfInCellar_SameHierarchy: + +the strange scalings of cellar and dwarf are intended. diff --git a/test/models/IRRMesh/credits.txt b/test/models/IRRMesh/credits.txt index 76ae3cb5d..a12163233 100644 --- a/test/models/IRRMesh/credits.txt +++ b/test/models/IRRMesh/credits.txt @@ -1,2 +1,2 @@ -cellar.irrmesh - From irrlight/irrEdit. Irrlicht/irredit license (which?) +cellar.irrmesh - From irrlight/irrEdit. Irrlicht/irredit license (which?) Textures resized to 400*400, improved JPEG compression to make them smaller \ No newline at end of file diff --git a/test/models/LWO/LWO2/MappingModes/earthCylindric.txt b/test/models/LWO/LWO2/MappingModes/earthCylindric.txt index 329b2f85a..46660a486 100644 --- a/test/models/LWO/LWO2/MappingModes/earthCylindric.txt +++ b/test/models/LWO/LWO2/MappingModes/earthCylindric.txt @@ -1,5 +1,5 @@ -Wikipedia Commons, -downloaded November 25th 08 - - +Wikipedia Commons, +downloaded November 25th 08 + + http://upload.wikimedia.org/wikipedia/commons/0/01/Lambert-cylindrical-equal-area-projection.jpg \ No newline at end of file diff --git a/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt b/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt index f47970009..218b339e1 100644 --- a/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt +++ b/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt @@ -1,9 +1,9 @@ -Source: - -Nasa, Monthly Global Images - -http://earthobservatory.nasa.gov/Features/BlueMarble/BlueMarble_monthlies.php - - -Downloaded November 24, 08. +Source: + +Nasa, Monthly Global Images + +http://earthobservatory.nasa.gov/Features/BlueMarble/BlueMarble_monthlies.php + + +Downloaded November 24, 08. Rescaled to 2048 * 1024 with GIMP \ No newline at end of file diff --git a/test/models/LWO/LWO2/concrete.source.txt b/test/models/LWO/LWO2/concrete.source.txt index de419f814..792fd1f89 100644 --- a/test/models/LWO/LWO2/concrete.source.txt +++ b/test/models/LWO/LWO2/concrete.source.txt @@ -1,2 +1,2 @@ -cgtextures.com - free, even for commercial use. See the licensing conditions and the FAQ the site for mroe details. +cgtextures.com - free, even for commercial use. See the licensing conditions and the FAQ the site for mroe details. Great source for free textures, btw! \ No newline at end of file diff --git a/test/models/LWO/LWO2/uvtest-source.txt b/test/models/LWO/LWO2/uvtest-source.txt index e534a4608..75e4878a7 100644 --- a/test/models/LWO/LWO2/uvtest-source.txt +++ b/test/models/LWO/LWO2/uvtest-source.txt @@ -1,2 +1,2 @@ -Regression file. +Regression file. by Tom Speed, see http://groups.google.com/group/bmx3d/browse_thread/thread/36db3b191f81be36 \ No newline at end of file diff --git a/test/models/MD2/faerie-source.txt b/test/models/MD2/faerie-source.txt index ea7ed82bb..ef0e4f196 100644 --- a/test/models/MD2/faerie-source.txt +++ b/test/models/MD2/faerie-source.txt @@ -1,24 +1,24 @@ - -From IRRLICHT/media - - -The Irrlicht Engine License - =========================== - - Copyright (C) 2002-2007 Nikolaus Gebhardt - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgement in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be clearly marked as such, and must not be - misrepresented as being the original software. + +From IRRLICHT/media + + +The Irrlicht Engine License + =========================== + + Copyright (C) 2002-2007 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/test/models/MD2/sidney-source.txt b/test/models/MD2/sidney-source.txt index ea7ed82bb..ef0e4f196 100644 --- a/test/models/MD2/sidney-source.txt +++ b/test/models/MD2/sidney-source.txt @@ -1,24 +1,24 @@ - -From IRRLICHT/media - - -The Irrlicht Engine License - =========================== - - Copyright (C) 2002-2007 Nikolaus Gebhardt - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgement in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be clearly marked as such, and must not be - misrepresented as being the original software. + +From IRRLICHT/media + + +The Irrlicht Engine License + =========================== + + Copyright (C) 2002-2007 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt b/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt index db69818e0..c2ca7c696 100644 --- a/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt +++ b/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt @@ -1,6 +1,6 @@ -My name: Grimmmy -Hi everybody!!! -This is my first published model so it isn't very good,but i'm still learning!.. -This model is free for everybody,but credit will be nice! -You may reach me at rojkov91@mail.ru +My name: Grimmmy +Hi everybody!!! +This is my first published model so it isn't very good,but i'm still learning!.. +This model is free for everybody,but credit will be nice! +You may reach me at rojkov91@mail.ru P.S: Excuse my bad english \ No newline at end of file diff --git a/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt b/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt index db69818e0..c2ca7c696 100644 --- a/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt +++ b/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt @@ -1,6 +1,6 @@ -My name: Grimmmy -Hi everybody!!! -This is my first published model so it isn't very good,but i'm still learning!.. -This model is free for everybody,but credit will be nice! -You may reach me at rojkov91@mail.ru +My name: Grimmmy +Hi everybody!!! +This is my first published model so it isn't very good,but i'm still learning!.. +This model is free for everybody,but credit will be nice! +You may reach me at rojkov91@mail.ru P.S: Excuse my bad english \ No newline at end of file diff --git a/test/models/MS3D/jeep1.readme.txt b/test/models/MS3D/jeep1.readme.txt index 14b0bd9eb..d17d5e0e9 100644 --- a/test/models/MS3D/jeep1.readme.txt +++ b/test/models/MS3D/jeep1.readme.txt @@ -1,15 +1,15 @@ -Jeep designed, modelled and skinned by me, Psionic - -FREE for use however you like, credits are appreciated!!! - -It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. - -I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! - -Check out more of my work at:- - -http://xu1productions.com/3dstudio/index.html - 3D Game Resources - -http://www.psionicdesign.com - My Main 2D/3D Digital Art site - +Jeep designed, modelled and skinned by me, Psionic + +FREE for use however you like, credits are appreciated!!! + +It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. + +I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! + +Check out more of my work at:- + +http://xu1productions.com/3dstudio/index.html - 3D Game Resources + +http://www.psionicdesign.com - My Main 2D/3D Digital Art site + Psionic 2002 \ No newline at end of file diff --git a/test/models/Q3D/E-AT-AT.source.txt b/test/models/Q3D/E-AT-AT.source.txt index b583e19c0..56a96f7d5 100644 --- a/test/models/Q3D/E-AT-AT.source.txt +++ b/test/models/Q3D/E-AT-AT.source.txt @@ -1,8 +1,8 @@ -Source: the3darchive.com - -Downloaded 4th November 08 (Obama ftw!) - -Copyright notice found on the page: - -Where do the models in the archive come from? +Source: the3darchive.com + +Downloaded 4th November 08 (Obama ftw!) + +Copyright notice found on the page: + +Where do the models in the archive come from? All 3D files available from the3darchive.com are from the public domain. \ No newline at end of file diff --git a/test/models/Q3D/earth.source.txt b/test/models/Q3D/earth.source.txt index b583e19c0..56a96f7d5 100644 --- a/test/models/Q3D/earth.source.txt +++ b/test/models/Q3D/earth.source.txt @@ -1,8 +1,8 @@ -Source: the3darchive.com - -Downloaded 4th November 08 (Obama ftw!) - -Copyright notice found on the page: - -Where do the models in the archive come from? +Source: the3darchive.com + +Downloaded 4th November 08 (Obama ftw!) + +Copyright notice found on the page: + +Where do the models in the archive come from? All 3D files available from the3darchive.com are from the public domain. \ No newline at end of file diff --git a/test/models/WRL/credits.txt b/test/models/WRL/credits.txt index 8024aeb81..055f73734 100644 --- a/test/models/WRL/credits.txt +++ b/test/models/WRL/credits.txt @@ -1,2 +1,2 @@ -"MotionCaptureROM.ase" Recorded using ViconIQ. -Converted to VRML with 3DS Max 2008. +"MotionCaptureROM.ase" Recorded using ViconIQ. +Converted to VRML with 3DS Max 2008. diff --git a/test/models/X/anim_test.txt b/test/models/X/anim_test.txt index ca759fd12..637ea0581 100644 --- a/test/models/X/anim_test.txt +++ b/test/models/X/anim_test.txt @@ -1,9 +1,9 @@ -Zylinder animation: - -Frame 1 - 10: Zylinder knickt ein, so dass der Knick in Richtung z+ zeigt. -Frame 10 - 18: Zylinder-Spitze streckt sich in Richtung z-. -Frame 18 - 24: Zylinder-Spitze bewegt sich zu Position in Richtung x+ - -Remarks: The exporter failed here for some reasons... although the mesh referres to four bones, only two of them are stored in the corresponding node hierarchy. So you have a mesh with 4 bones, a hirarchy with 2 nodes and a animation that affects only those two nodes. - +Zylinder animation: + +Frame 1 - 10: Zylinder knickt ein, so dass der Knick in Richtung z+ zeigt. +Frame 10 - 18: Zylinder-Spitze streckt sich in Richtung z-. +Frame 18 - 24: Zylinder-Spitze bewegt sich zu Position in Richtung x+ + +Remarks: The exporter failed here for some reasons... although the mesh referres to four bones, only two of them are stored in the corresponding node hierarchy. So you have a mesh with 4 bones, a hirarchy with 2 nodes and a animation that affects only those two nodes. + There is no timing given for the animation. You have to scale the animation manually. For this file, the timing seems to be 24 ticks per second. \ No newline at end of file diff --git a/test/models/X/kwxport_test_cubewithvcolors.source.txt b/test/models/X/kwxport_test_cubewithvcolors.source.txt index d173f5a47..94ee48e4a 100644 --- a/test/models/X/kwxport_test_cubewithvcolors.source.txt +++ b/test/models/X/kwxport_test_cubewithvcolors.source.txt @@ -1,16 +1,16 @@ -From kwxport -http://www.kwxport.org/ - ->> -The kW Xport plug-in source is released under the MIT license. -Basically, it means "feel free to use it; credit the source; don't sue me -if something goes wrong." ->> - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +From kwxport +http://www.kwxport.org/ + +>> +The kW Xport plug-in source is released under the MIT license. +Basically, it means "feel free to use it; credit the source; don't sue me +if something goes wrong." +>> + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test/models/X/test.txt b/test/models/X/test.txt index 1f7698422..7a5e8e74b 100644 --- a/test/models/X/test.txt +++ b/test/models/X/test.txt @@ -1,3 +1,3 @@ -Simple textured test cube exported from Maya. Has a texture that does label each cube side uniquely, but the sides do not match DirectX coordinate space. - +Simple textured test cube exported from Maya. Has a texture that does label each cube side uniquely, but the sides do not match DirectX coordinate space. + Is not readable using D3DXLoadFrameHierarchy, needs custom text parsing. \ No newline at end of file diff --git a/test/models/invalid/readme.txt b/test/models/invalid/readme.txt index 50b5fc1ce..cab740a84 100644 --- a/test/models/invalid/readme.txt +++ b/test/models/invalid/readme.txt @@ -1,31 +1,31 @@ - -********************************************************* -GENERAL -********************************************************* - - -The files in this directory are invalid ... some of them are empty, -others have invalid vertices or faces, others are prepared to make - assimp allocate a few hundreds gigs of memory ... most are -actually regression tests, i.e. there was once a bugfix that -fixed the respective loaders. - -This test case is successful if the library (and the viewer) don't -crash. - - -********************************************************* -FILES -********************************************************* - -OutOfMemory.off - the number of faces is invalid. There won't be - enough memory so std::vector::reserve() will most likely fail. - The exception should be caught in Importer.cpp. - -empty. - These files are completely empty. The corresponding - loaders should not crash. - -malformed.obj - out-of-range vertex indices -malformed2.obj - non-existent material referenced - - + +********************************************************* +GENERAL +********************************************************* + + +The files in this directory are invalid ... some of them are empty, +others have invalid vertices or faces, others are prepared to make + assimp allocate a few hundreds gigs of memory ... most are +actually regression tests, i.e. there was once a bugfix that +fixed the respective loaders. + +This test case is successful if the library (and the viewer) don't +crash. + + +********************************************************* +FILES +********************************************************* + +OutOfMemory.off - the number of faces is invalid. There won't be + enough memory so std::vector::reserve() will most likely fail. + The exception should be caught in Importer.cpp. + +empty. - These files are completely empty. The corresponding + loaders should not crash. + +malformed.obj - out-of-range vertex indices +malformed2.obj - non-existent material referenced + + diff --git a/test/unit/utIOSystem.cpp b/test/unit/utIOSystem.cpp new file mode 100644 index 000000000..b44976488 --- /dev/null +++ b/test/unit/utIOSystem.cpp @@ -0,0 +1,94 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, 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 + +using namespace std; +using namespace Assimp; + +static const string Sep = "/"; +class TestIOSystem : public IOSystem { +public: + TestIOSystem() : IOSystem() {} + virtual ~TestIOSystem() {} + virtual bool Exists( const char* ) const { + return true; + } + virtual char getOsSeparator() const { + return Sep[ 0 ]; + } + + virtual IOStream* Open(const char* pFile, const char* pMode = "rb") { + return NULL; + } + + virtual void Close( IOStream* pFile) { + // empty + } +}; + +class IOSystemTest : public ::testing::Test { +public: + virtual void SetUp() { pImp = new TestIOSystem(); } + virtual void TearDown() { delete pImp; } + +protected: + TestIOSystem* pImp; +}; + +/* +virtual bool PushDirectory( const std::string &path ); +virtual const std::string &CurrentDirectory() const; +virtual bool PopDirectory(); +*/ + +TEST_F( IOSystemTest, accessDirectoryStackTest ) { + EXPECT_FALSE( pImp->PopDirectory() ); + EXPECT_EQ( 0, pImp->StackSize() ); + EXPECT_FALSE( pImp->PushDirectory( "" ) ); + std::string path = "test/"; + EXPECT_TRUE( pImp->PushDirectory( path ) ); + EXPECT_EQ( 1, pImp->StackSize() ); + EXPECT_EQ( path, pImp->CurrentDirectory() ); + EXPECT_TRUE( pImp->PopDirectory() ); + EXPECT_EQ( 0, pImp->StackSize() ); +} diff --git a/workspaces/xcode3/info.txt b/workspaces/xcode3/info.txt index 4a623d1ed..d22a76b6f 100644 --- a/workspaces/xcode3/info.txt +++ b/workspaces/xcode3/info.txt @@ -1,6 +1,6 @@ -The xcode project files in this directory are contributed by Andy Maloney and are not continuously updated. -Currently, it's for Assimp r352. If you're using a newer revision, watch out for missing files/includes/... - -See Andy's description at -http://sourceforge.net/tracker/index.php?func=detail&aid=2659135&group_id=226462&atid=1067634 (Tracker item 2659135) -for more information. +The xcode project files in this directory are contributed by Andy Maloney and are not continuously updated. +Currently, it's for Assimp r352. If you're using a newer revision, watch out for missing files/includes/... + +See Andy's description at +http://sourceforge.net/tracker/index.php?func=detail&aid=2659135&group_id=226462&atid=1067634 (Tracker item 2659135) +for more information. diff --git a/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj b/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj new file mode 100644 index 000000000..14c4598bd --- /dev/null +++ b/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj @@ -0,0 +1,1980 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7F79242A1AB43E20005A8E5D /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 15221A74FC9C4B2AAA7306E3 /* 3DSConverter.cpp */; }; + 7F79242B1AB43E20005A8E5D /* 3DSExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECCBBF2D75A44335AB93C84A /* 3DSExporter.cpp */; }; + 7F79242C1AB43E20005A8E5D /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E9476D129940BF84DE6682 /* 3DSLoader.cpp */; }; + 7F79242D1AB43E20005A8E5D /* ACLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1076BAC69DB4935A93045A8 /* ACLoader.cpp */; }; + 7F79242E1AB43E20005A8E5D /* ASELoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C477FA4D89548F1BCEDC5A0 /* ASELoader.cpp */; }; + 7F79242F1AB43E20005A8E5D /* ASEParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 929F59CCA32549EC884A5033 /* ASEParser.cpp */; }; + 7F7924301AB43E20005A8E5D /* AssbinExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6389F68312384CFD847B1D13 /* AssbinExporter.cpp */; }; + 7F7924311AB43E20005A8E5D /* AssbinLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9FEEF58B24548F782A5D53C /* AssbinLoader.cpp */; }; + 7F7924321AB43E20005A8E5D /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 705D30EE141A48F292783F0E /* Assimp.cpp */; }; + 7F7924331AB43E20005A8E5D /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A9535EDF9A4FF2B8DABD7D /* AssimpCExport.cpp */; }; + 7F7924351AB43E20005A8E5D /* AssxmlExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B3E8A1BEF8E74F04AE06871B /* AssxmlExporter.cpp */; }; + 7F7924361AB43E20005A8E5D /* B3DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FCCB4BB481FB461688FE2F29 /* B3DImporter.cpp */; }; + 7F7924371AB43E20005A8E5D /* BVHLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C80B9A3AF4204AE08AA50BAE /* BVHLoader.cpp */; }; + 7F7924381AB43E20005A8E5D /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A58410FEAA884A2D8D73ACCE /* BaseImporter.cpp */; }; + 7F7924391AB43E20005A8E5D /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB6BC13FCFE40F5801D0972 /* BaseProcess.cpp */; }; + 7F79243A1AB43E20005A8E5D /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 10238FBD7A9D401A82D667CB /* Bitmap.cpp */; }; + 7F79243B1AB43E20005A8E5D /* BlenderBMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 603AFA882AFF49AEAC2C8FA2 /* BlenderBMesh.cpp */; }; + 7F79243C1AB43E20005A8E5D /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65258E349704523BC43904D /* BlenderDNA.cpp */; }; + 7F79243D1AB43E20005A8E5D /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 906F71D342544BF381E1318E /* BlenderLoader.cpp */; }; + 7F79243E1AB43E20005A8E5D /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3106D75C13874F5AB3EBBFE7 /* BlenderModifier.cpp */; }; + 7F79243F1AB43E20005A8E5D /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE0D259917354C80BE1CC791 /* BlenderScene.cpp */; }; + 7F7924401AB43E20005A8E5D /* BlenderTessellator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 12C5DD7A285042EDB1897FAE /* BlenderTessellator.cpp */; }; + 7F7924411AB43E20005A8E5D /* COBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C84DA0E6CE13493D833BA1C1 /* COBLoader.cpp */; }; + 7F7924421AB43E20005A8E5D /* CSMLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77908990BEF04D0881E8AE80 /* CSMLoader.cpp */; }; + 7F7924431AB43E20005A8E5D /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90DD6CA40A5E41458E11FF3E /* CalcTangentsProcess.cpp */; }; + 7F7924441AB43E20005A8E5D /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C0527629078403F81CFD117 /* ColladaExporter.cpp */; }; + 7F7924451AB43E20005A8E5D /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A4706D216414D4F8AA72EC9 /* ColladaLoader.cpp */; }; + 7F7924461AB43E20005A8E5D /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 420D77ED33554D54AA4D50EF /* ColladaParser.cpp */; }; + 7F7924471AB43E20005A8E5D /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ABBB4561E72413EB40702C3 /* ComputeUVMappingProcess.cpp */; }; + 7F7924481AB43E20005A8E5D /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92D8734FFF9742B39A371B70 /* ConvertToLHProcess.cpp */; }; + 7F7924491AB43E20005A8E5D /* DXFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 466D6B9A7CCD402D9AA87071 /* DXFLoader.cpp */; }; + 7F79244A1AB43E20005A8E5D /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E20FCC571F144DDBD831CCB /* DeboneProcess.cpp */; }; + 7F79244B1AB43E20005A8E5D /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9FEF4D69EFC4605A4F752E5 /* DefaultIOStream.cpp */; }; + 7F79244C1AB43E20005A8E5D /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D502654EF864101A2DA9476 /* DefaultIOSystem.cpp */; }; + 7F79244D1AB43E20005A8E5D /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9E9EB834E09420197C3FB8C /* DefaultLogger.cpp */; }; + 7F79244E1AB43E20005A8E5D /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FF4E90FB1A3446F095ECC8BD /* Exporter.cpp */; }; + 7F79244F1AB43E20005A8E5D /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAD34F1AA6664B6B935C9421 /* FBXAnimation.cpp */; }; + 7F7924501AB43E20005A8E5D /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1108AC28566B4D2B9F27C691 /* FBXBinaryTokenizer.cpp */; }; + 7F7924511AB43E20005A8E5D /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A56A688A3845768410F500 /* FBXConverter.cpp */; }; + 7F7924521AB43E20005A8E5D /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9855496CEA774F4FA7FBB862 /* FBXDeformer.cpp */; }; + 7F7924531AB43E20005A8E5D /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22D5BA425444A028DA42BEA /* FBXDocument.cpp */; }; + 7F7924541AB43E20005A8E5D /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB38E7E7661842448F008372 /* FBXDocumentUtil.cpp */; }; + 7F7924551AB43E20005A8E5D /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B4C688FA08F44716855CDD3C /* FBXImporter.cpp */; }; + 7F7924561AB43E20005A8E5D /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE6163EB035149A6B8139DB8 /* FBXMaterial.cpp */; }; + 7F7924571AB43E20005A8E5D /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42E110B9E6924AF9B55AE65A /* FBXMeshGeometry.cpp */; }; + 7F7924581AB43E20005A8E5D /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A61BDC559CE4186B03C0396 /* FBXModel.cpp */; }; + 7F7924591AB43E20005A8E5D /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33B70115CA54405F895BA471 /* FBXNodeAttribute.cpp */; }; + 7F79245A1AB43E20005A8E5D /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5F373DF3B03B4B848B78EAD2 /* FBXParser.cpp */; }; + 7F79245B1AB43E20005A8E5D /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9D203F78B24C4D7E8E2084A3 /* FBXProperties.cpp */; }; + 7F79245C1AB43E20005A8E5D /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF07D05DC86F4C98BC42FDCF /* FBXTokenizer.cpp */; }; + 7F79245D1AB43E20005A8E5D /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E6332CD992D447CA910DA456 /* FBXUtil.cpp */; }; + 7F79245E1AB43E20005A8E5D /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BABB7734139C452A9DDEE797 /* FindDegenerates.cpp */; }; + 7F79245F1AB43E20005A8E5D /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A101D1311C4E77AAEDD94C /* FindInstancesProcess.cpp */; }; + 7F7924601AB43E20005A8E5D /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4221AA0AD2418FAA45EB64 /* FindInvalidDataProcess.cpp */; }; + 7F7924611AB43E20005A8E5D /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C54518F708BA4A328D5D7325 /* FixNormalsStep.cpp */; }; + 7F7924621AB43E20005A8E5D /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 982AE676D2364350B1FBD095 /* GenFaceNormalsProcess.cpp */; }; + 7F7924631AB43E20005A8E5D /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A0AED12A1A6D4635A8CFB65A /* GenVertexNormalsProcess.cpp */; }; + 7F7924641AB43E20005A8E5D /* HMPLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43ABFF591F374920A5E18A24 /* HMPLoader.cpp */; }; + 7F7924651AB43E20005A8E5D /* IFCBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 285D1FDA48EC4DD8933B603E /* IFCBoolean.cpp */; }; + 7F7924661AB43E20005A8E5D /* IFCCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E7FD92FFCF441B0A60FC8B4 /* IFCCurve.cpp */; }; + 7F7924671AB43E20005A8E5D /* IFCGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3267EBBA6EEB435F83FF25E4 /* IFCGeometry.cpp */; }; + 7F7924681AB43E20005A8E5D /* IFCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0E9BB0220704C5D93CE7CE9 /* IFCLoader.cpp */; }; + 7F7924691AB43E20005A8E5D /* IFCMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0014AE5E87A74AAA9EF0EC4B /* IFCMaterial.cpp */; }; + 7F79246A1AB43E20005A8E5D /* IFCOpenings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74679D2078FD46ED9AC73355 /* IFCOpenings.cpp */; }; + 7F79246B1AB43E20005A8E5D /* IFCProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46E9F455A3284DB399986293 /* IFCProfile.cpp */; }; + 7F79246C1AB43E20005A8E5D /* IFCReaderGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F5D1E6368384D429BA29D5A /* IFCReaderGen.cpp */; }; + 7F79246D1AB43E20005A8E5D /* IFCUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59E3D32E3FC7438DB148537F /* IFCUtil.cpp */; }; + 7F79246E1AB43E20005A8E5D /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97DFA90F9D0C4B999C150B10 /* IRRLoader.cpp */; }; + 7F79246F1AB43E20005A8E5D /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7FFD53046F4AEB898C0832 /* IRRMeshLoader.cpp */; }; + 7F7924701AB43E20005A8E5D /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CC54A231FF6B4B0CABCFD167 /* IRRShared.cpp */; }; + 7F7924711AB43E20005A8E5D /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9472EFB6831740DD91471337 /* Importer.cpp */; }; + 7F7924721AB43E20005A8E5D /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D029CE902F8045B0B3AFFDDB /* ImporterRegistry.cpp */; }; + 7F7924731AB43E20005A8E5D /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D5FDFA995E45E6A3E8FD37 /* ImproveCacheLocality.cpp */; }; + 7F7924741AB43E20005A8E5D /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B36DA471B9E142FC9425EC45 /* JoinVerticesProcess.cpp */; }; + 7F7924751AB43E20005A8E5D /* LWOAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 680C392FFE0B4CC5ABC7CA64 /* LWOAnimation.cpp */; }; + 7F7924761AB43E20005A8E5D /* LWOBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D629F6BF53864979B7619067 /* LWOBLoader.cpp */; }; + 7F7924771AB43E20005A8E5D /* LWOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5A4E05386C094B809A315A07 /* LWOLoader.cpp */; }; + 7F7924781AB43E20005A8E5D /* LWOMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ED21FC57A384CE6B4F53C0C /* LWOMaterial.cpp */; }; + 7F7924791AB43E20005A8E5D /* LWSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFF41974881F466A9561BE4B /* LWSLoader.cpp */; }; + 7F79247A1AB43E20005A8E5D /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E065DB38B0284196A9283CA3 /* LimitBoneWeightsProcess.cpp */; }; + 7F79247B1AB43E20005A8E5D /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49B655CCE1314D4E8A94B371 /* MD2Loader.cpp */; }; + 7F79247C1AB43E20005A8E5D /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 563FBACCFD774BDEA4AEAC10 /* MD3Loader.cpp */; }; + 7F79247D1AB43E20005A8E5D /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A277DBC1EFB944F995659A20 /* MD5Loader.cpp */; }; + 7F79247E1AB43E20005A8E5D /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BC5FD00572F4C58B267A0EC /* MD5Parser.cpp */; }; + 7F79247F1AB43E20005A8E5D /* MDCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35E4944C052A4C91BF31DE5F /* MDCLoader.cpp */; }; + 7F7924801AB43E20005A8E5D /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA92FFC8B06D4569AD9C4CB1 /* MDLLoader.cpp */; }; + 7F7924811AB43E20005A8E5D /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CEC69808E1844C23B95D3475 /* MDLMaterialLoader.cpp */; }; + 7F7924821AB43E20005A8E5D /* MS3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A990C6FF244DC397B7BA7C /* MS3DLoader.cpp */; }; + 7F7924831AB43E20005A8E5D /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21B797DAB0E0427C9339AE0F /* MakeVerboseFormat.cpp */; }; + 7F7924841AB43E20005A8E5D /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FF72CB6E99E40E19AE0E64C /* MaterialSystem.cpp */; }; + 7F7924851AB43E20005A8E5D /* NDOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B4F1B5789CA540C78FB9219D /* NDOLoader.cpp */; }; + 7F7924861AB43E20005A8E5D /* NFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0D6E8E292F594A2DAFF53564 /* NFFLoader.cpp */; }; + 7F7924871AB43E20005A8E5D /* OFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EFD557FE2C3A46D78F070655 /* OFFLoader.cpp */; }; + 7F7924881AB43E20005A8E5D /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE811A81663A492A84E13937 /* ObjExporter.cpp */; }; + 7F7924891AB43E20005A8E5D /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 862131D4574B4CABA5EC957B /* ObjFileImporter.cpp */; }; + 7F79248A1AB43E20005A8E5D /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4108529663904025B21E526B /* ObjFileMtlImporter.cpp */; }; + 7F79248B1AB43E20005A8E5D /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ACF73EEAB2424213BF7158D5 /* ObjFileParser.cpp */; }; + 7F79248C1AB43E20005A8E5D /* OgreBinarySerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56ADEC4899C047F2839AD791 /* OgreBinarySerializer.cpp */; }; + 7F79248D1AB43E20005A8E5D /* OgreImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 923283A9791E4B4E86D623FC /* OgreImporter.cpp */; }; + 7F79248E1AB43E20005A8E5D /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F75457C6D026451B9267B65E /* OgreMaterial.cpp */; }; + 7F79248F1AB43E20005A8E5D /* OgreStructs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A49EFE23E34E1CBA2E4377 /* OgreStructs.cpp */; }; + 7F7924901AB43E20005A8E5D /* OgreXmlSerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EF9F805A4BA4428CA98C9DE5 /* OgreXmlSerializer.cpp */; }; + 7F7924911AB43E20005A8E5D /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAB9AE5328F843F5A8A3E85C /* OptimizeGraph.cpp */; }; + 7F7924921AB43E20005A8E5D /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACC87E846AE4E4A86E1AEF4 /* OptimizeMeshes.cpp */; }; + 7F7924931AB43E20005A8E5D /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E51043448F1744FFA78526D5 /* PlyExporter.cpp */; }; + 7F7924941AB43E20005A8E5D /* PlyLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 409C98EE093C499B8A574CA9 /* PlyLoader.cpp */; }; + 7F7924951AB43E20005A8E5D /* PlyParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D504725E540109530E254 /* PlyParser.cpp */; }; + 7F7924961AB43E20005A8E5D /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E663847651834244834CB9F5 /* PostStepRegistry.cpp */; }; + 7F7924971AB43E20005A8E5D /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 023C115651B54570AA2040DB /* PretransformVertices.cpp */; }; + 7F7924981AB43E20005A8E5D /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 890E32C714444692AA016AE5 /* ProcessHelper.cpp */; }; + 7F7924991AB43E20005A8E5D /* Q3BSPFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A88D56FBEA084A3EA9A0ECB3 /* Q3BSPFileImporter.cpp */; }; + 7F79249A1AB43E20005A8E5D /* Q3BSPFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A60A00727F04E049CF3AE33 /* Q3BSPFileParser.cpp */; }; + 7F79249B1AB43E20005A8E5D /* Q3BSPZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43C75175738C4119871E8BB0 /* Q3BSPZipArchive.cpp */; }; + 7F79249C1AB43E20005A8E5D /* Q3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5178B3983F147F3B9BD8217 /* Q3DLoader.cpp */; }; + 7F79249D1AB43E20005A8E5D /* RawLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D4A669762194B9D9A26DD20 /* RawLoader.cpp */; }; + 7F79249E1AB43E20005A8E5D /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A86069DEEDC42B88634F78D /* RemoveComments.cpp */; }; + 7F79249F1AB43E20005A8E5D /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADACEBC4973F4FC0A6FEC68A /* RemoveRedundantMaterials.cpp */; }; + 7F7924A01AB43E20005A8E5D /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB4ABA17AF264257BDA4D921 /* RemoveVCProcess.cpp */; }; + 7F7924A11AB43E20005A8E5D /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52836A0629E24447B924750A /* SGSpatialSort.cpp */; }; + 7F7924A21AB43E20005A8E5D /* SMDLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD9BEC6B8A264AB092F98E20 /* SMDLoader.cpp */; }; + 7F7924A31AB43E20005A8E5D /* STEPFileEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E11A39E91576445599DF2AC4 /* STEPFileEncoding.cpp */; }; + 7F7924A41AB43E20005A8E5D /* STEPFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE3ECA98173418A9F997992 /* STEPFileReader.cpp */; }; + 7F7924A51AB43E20005A8E5D /* STLExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 89D2D359BD854D8AA60CB720 /* STLExporter.cpp */; }; + 7F7924A61AB43E20005A8E5D /* STLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D2F1605B9484B08BB33402D /* STLLoader.cpp */; }; + 7F7924A71AB43E20005A8E5D /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 73A3D87FF2C04C3BA3684F54 /* SceneCombiner.cpp */; }; + 7F7924A81AB43E20005A8E5D /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1775DE08FC8647EB896A0FB3 /* ScenePreprocessor.cpp */; }; + 7F7924A91AB43E20005A8E5D /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B2827B3E64147E08A5AD334 /* SkeletonMeshBuilder.cpp */; }; + 7F7924AA1AB43E20005A8E5D /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD9A81E0E27E44718609615B /* SortByPTypeProcess.cpp */; }; + 7F7924AB1AB43E20005A8E5D /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EEC6646FC044D1E9658A590 /* SpatialSort.cpp */; }; + 7F7924AC1AB43E20005A8E5D /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99A4349D505F4CC593F48CF6 /* SplitByBoneCountProcess.cpp */; }; + 7F7924AD1AB43E20005A8E5D /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A43641DC9C1B4B578BC40476 /* SplitLargeMeshes.cpp */; }; + 7F7924AE1AB43E20005A8E5D /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C18C5023460E4D17B8C922D7 /* StandardShapes.cpp */; }; + 7F7924AF1AB43E20005A8E5D /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDEB63CFEB4F2EAA95358D /* Subdivision.cpp */; }; + 7F7924B01AB43E20005A8E5D /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6F65B6129F774AEDB8DC845A /* TargetAnimation.cpp */; }; + 7F7924B11AB43E20005A8E5D /* TerragenLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4866DA5A7BFD49F79B61CBF8 /* TerragenLoader.cpp */; }; + 7F7924B21AB43E20005A8E5D /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF76D04D95E649BCBC15E64F /* TextureTransform.cpp */; }; + 7F7924B31AB43E20005A8E5D /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0AC303D18A48A69AB3BC03 /* TriangulateProcess.cpp */; }; + 7F7924B41AB43E20005A8E5D /* UnrealLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B8FD96D46314ACD8F157AC3 /* UnrealLoader.cpp */; }; + 7F7924B51AB43E20005A8E5D /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EF4F7A237F648C2809A8F31 /* ValidateDataStructure.cpp */; }; + 7F7924B61AB43E20005A8E5D /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AAF26EBF0A64ABDB840BA64 /* VertexTriangleAdjacency.cpp */; }; + 7F7924B71AB43E20005A8E5D /* XFileExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 435DC362E63D4CCBA68656D3 /* XFileExporter.cpp */; }; + 7F7924B81AB43E20005A8E5D /* XFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06DB494DCE4D47FDA00E8B35 /* XFileImporter.cpp */; }; + 7F7924B91AB43E20005A8E5D /* XFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C02A113B804568A7E39CBC /* XFileParser.cpp */; }; + 7F7924BA1AB43E20005A8E5D /* XGLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E395349546A4FDF843E6963 /* XGLLoader.cpp */; }; + 7F7924BB1AB43E20005A8E5D /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 9A0960F123634603B15EEA38 /* ConvertUTF.c */; }; + 7F7924BC1AB43E20005A8E5D /* clipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59F8A11A7AED45CC94CEDF28 /* clipper.cpp */; }; + 7F7924BD1AB43E20005A8E5D /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 64C6BACDA5DD4139AA26EE81 /* irrXML.cpp */; }; + 7F7924BE1AB43E20005A8E5D /* shapes.cc in Sources */ = {isa = PBXBuildFile; fileRef = AE00939F150F413780C8AAD7 /* shapes.cc */; }; + 7F7924BF1AB43E20005A8E5D /* advancing_front.cc in Sources */ = {isa = PBXBuildFile; fileRef = B72D0BA3EF66439F8D582ED3 /* advancing_front.cc */; }; + 7F7924C01AB43E20005A8E5D /* cdt.cc in Sources */ = {isa = PBXBuildFile; fileRef = 849EC6315E4A4E5FA06521EA /* cdt.cc */; }; + 7F7924C11AB43E20005A8E5D /* sweep.cc in Sources */ = {isa = PBXBuildFile; fileRef = 49E993CD86A346869AF473BC /* sweep.cc */; }; + 7F7924C21AB43E20005A8E5D /* sweep_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5E10483FBE6D4F4594B460E0 /* sweep_context.cc */; }; + 7F7924C31AB43E20005A8E5D /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = AF75E6049338489BB256D295 /* ioapi.c */; }; + 7F7924C41AB43E20005A8E5D /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 973D4231A4AA4925B019FEEE /* unzip.c */; }; + 7F7A93A81B65D0110094C4DA /* DDLNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F7A93A51B65D0110094C4DA /* DDLNode.cpp */; }; + 7F7A93A91B65D0110094C4DA /* OpenDDLParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F7A93A61B65D0110094C4DA /* OpenDDLParser.cpp */; }; + 7F7A93AA1B65D0110094C4DA /* Value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F7A93A71B65D0110094C4DA /* Value.cpp */; }; + 7FBE9FEA1B65AC1200D2115E /* OpenGEXExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBE9FE51B65AC1200D2115E /* OpenGEXExporter.cpp */; }; + 7FBE9FEB1B65AC1200D2115E /* OpenGEXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBE9FE71B65AC1200D2115E /* OpenGEXImporter.cpp */; }; + 7FBEA0121B65B11800D2115E /* Version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBEA0111B65B11800D2115E /* Version.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0014AE5E87A74AAA9EF0EC4B /* IFCMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCMaterial.cpp; path = code/IFCMaterial.cpp; sourceTree = SOURCE_ROOT; }; + 005DFE3B6FFC4BEBB7055330 /* ObjFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileData.h; path = code/ObjFileData.h; sourceTree = SOURCE_ROOT; }; + 00EB692107B84590B0560BFB /* MD4FileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD4FileData.h; path = code/MD4FileData.h; sourceTree = SOURCE_ROOT; }; + 023C115651B54570AA2040DB /* PretransformVertices.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PretransformVertices.cpp; path = code/PretransformVertices.cpp; sourceTree = SOURCE_ROOT; }; + 02587469A85540EE875B04B5 /* heapsort.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = heapsort.h; path = contrib/irrXML/heapsort.h; sourceTree = SOURCE_ROOT; }; + 02E9476D129940BF84DE6682 /* 3DSLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = 3DSLoader.cpp; path = code/3DSLoader.cpp; sourceTree = SOURCE_ROOT; }; + 0535CB113239433DA7CD7FDE /* color4.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = color4.h; path = include/assimp/color4.h; sourceTree = SOURCE_ROOT; }; + 05EA73C462244F1791039BFB /* material.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = material.h; path = include/assimp/material.h; sourceTree = SOURCE_ROOT; }; + 06DB494DCE4D47FDA00E8B35 /* XFileImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XFileImporter.cpp; path = code/XFileImporter.cpp; sourceTree = SOURCE_ROOT; }; + 073189BEE7A5466B9EE817D4 /* matrix3x3.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = matrix3x3.inl; path = include/assimp/matrix3x3.inl; sourceTree = SOURCE_ROOT; }; + 079B3C75D1014265959C427D /* color4.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = color4.inl; path = include/assimp/color4.inl; sourceTree = SOURCE_ROOT; }; + 08E8379F20984AD59515AD95 /* MD3FileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD3FileData.h; path = code/MD3FileData.h; sourceTree = SOURCE_ROOT; }; + 0A941971CBF04E8D900E9799 /* JoinVerticesProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = JoinVerticesProcess.h; path = code/JoinVerticesProcess.h; sourceTree = SOURCE_ROOT; }; + 0AA53AD6095A4D1088431EED /* MakeVerboseFormat.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MakeVerboseFormat.h; path = code/MakeVerboseFormat.h; sourceTree = SOURCE_ROOT; }; + 0AAF26EBF0A64ABDB840BA64 /* VertexTriangleAdjacency.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = VertexTriangleAdjacency.cpp; path = code/VertexTriangleAdjacency.cpp; sourceTree = SOURCE_ROOT; }; + 0B519CCAB4B241E59C567077 /* 3DSExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = 3DSExporter.h; path = code/3DSExporter.h; sourceTree = SOURCE_ROOT; }; + 0BC5FD00572F4C58B267A0EC /* MD5Parser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD5Parser.cpp; path = code/MD5Parser.cpp; sourceTree = SOURCE_ROOT; }; + 0C1B00249A554394A4F9CF2A /* ParsingUtils.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ParsingUtils.h; path = code/ParsingUtils.h; sourceTree = SOURCE_ROOT; }; + 0CCD090F58EB40ACBBDBBDEE /* AssbinLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = AssbinLoader.h; path = code/AssbinLoader.h; sourceTree = SOURCE_ROOT; }; + 0D6E8E292F594A2DAFF53564 /* NFFLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = NFFLoader.cpp; path = code/NFFLoader.cpp; sourceTree = SOURCE_ROOT; }; + 0EF256EC06E345EB930772EC /* FBXDocument.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXDocument.h; path = code/FBXDocument.h; sourceTree = SOURCE_ROOT; }; + 0EF4F7A237F648C2809A8F31 /* ValidateDataStructure.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ValidateDataStructure.cpp; path = code/ValidateDataStructure.cpp; sourceTree = SOURCE_ROOT; }; + 0FBF026F27F340AD9FABAF02 /* GenFaceNormalsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = GenFaceNormalsProcess.h; path = code/GenFaceNormalsProcess.h; sourceTree = SOURCE_ROOT; }; + 101172E4EF2E43D988B6B571 /* PretransformVertices.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PretransformVertices.h; path = code/PretransformVertices.h; sourceTree = SOURCE_ROOT; }; + 1011FC45108745A7BBA98904 /* IRRLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IRRLoader.h; path = code/IRRLoader.h; sourceTree = SOURCE_ROOT; }; + 10238FBD7A9D401A82D667CB /* Bitmap.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Bitmap.cpp; path = code/Bitmap.cpp; sourceTree = SOURCE_ROOT; }; + 10E9B0497D844A10BC759A09 /* matrix3x3.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = matrix3x3.h; path = include/assimp/matrix3x3.h; sourceTree = SOURCE_ROOT; }; + 1108AC28566B4D2B9F27C691 /* FBXBinaryTokenizer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXBinaryTokenizer.cpp; path = code/FBXBinaryTokenizer.cpp; sourceTree = SOURCE_ROOT; }; + 12C5DD7A285042EDB1897FAE /* BlenderTessellator.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderTessellator.cpp; path = code/BlenderTessellator.cpp; sourceTree = SOURCE_ROOT; }; + 12E167EBA81B4CD3A241D7AF /* irrXML.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrXML.h; path = contrib/irrXML/irrXML.h; sourceTree = SOURCE_ROOT; }; + 139DFC029C4C44B09952C645 /* material.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = material.inl; path = include/assimp/material.inl; sourceTree = SOURCE_ROOT; }; + 13BFADA520C04B15AE256CC2 /* IFCUtil.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFCUtil.h; path = code/IFCUtil.h; sourceTree = SOURCE_ROOT; }; + 1520A11AA6E54812939B1FBB /* FileLogStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FileLogStream.h; path = code/FileLogStream.h; sourceTree = SOURCE_ROOT; }; + 15221A74FC9C4B2AAA7306E3 /* 3DSConverter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = 3DSConverter.cpp; path = code/3DSConverter.cpp; sourceTree = SOURCE_ROOT; }; + 1533BE4C09F1430C8BF4D248 /* Vertex.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Vertex.h; path = code/Vertex.h; sourceTree = SOURCE_ROOT; }; + 157C3CC81232428FA535E05F /* BlenderLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderLoader.h; path = code/BlenderLoader.h; sourceTree = SOURCE_ROOT; }; + 16437E08A946431EB2EFA3E0 /* SortByPTypeProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SortByPTypeProcess.h; path = code/SortByPTypeProcess.h; sourceTree = SOURCE_ROOT; }; + 1775DE08FC8647EB896A0FB3 /* ScenePreprocessor.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ScenePreprocessor.cpp; path = code/ScenePreprocessor.cpp; sourceTree = SOURCE_ROOT; }; + 180177D50FDA4C10AD629DC2 /* ObjFileMtlImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileMtlImporter.h; path = code/ObjFileMtlImporter.h; sourceTree = SOURCE_ROOT; }; + 1A0AC303D18A48A69AB3BC03 /* TriangulateProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TriangulateProcess.cpp; path = code/TriangulateProcess.cpp; sourceTree = SOURCE_ROOT; }; + 1A4706D216414D4F8AA72EC9 /* ColladaLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ColladaLoader.cpp; path = code/ColladaLoader.cpp; sourceTree = SOURCE_ROOT; }; + 1A61BDC559CE4186B03C0396 /* FBXModel.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXModel.cpp; path = code/FBXModel.cpp; sourceTree = SOURCE_ROOT; }; + 1AF1EE8EFE594A40ACE03D19 /* fast_atof.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = fast_atof.h; path = code/fast_atof.h; sourceTree = SOURCE_ROOT; }; + 1BC6B0FE92DD4F38803BC17B /* CSMLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CSMLoader.h; path = code/CSMLoader.h; sourceTree = SOURCE_ROOT; }; + 1C0527629078403F81CFD117 /* ColladaExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ColladaExporter.cpp; path = code/ColladaExporter.cpp; sourceTree = SOURCE_ROOT; }; + 1CBCEE37D89145F19F23F036 /* MD3Loader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD3Loader.h; path = code/MD3Loader.h; sourceTree = SOURCE_ROOT; }; + 1D4A669762194B9D9A26DD20 /* RawLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RawLoader.cpp; path = code/RawLoader.cpp; sourceTree = SOURCE_ROOT; }; + 1D502654EF864101A2DA9476 /* DefaultIOSystem.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DefaultIOSystem.cpp; path = code/DefaultIOSystem.cpp; sourceTree = SOURCE_ROOT; }; + 1DC56C794E434BA28E5CCC36 /* format.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = format.hpp; path = code/BoostWorkaround/boost/format.hpp; sourceTree = SOURCE_ROOT; }; + 1ED21FC57A384CE6B4F53C0C /* LWOMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOMaterial.cpp; path = code/LWOMaterial.cpp; sourceTree = SOURCE_ROOT; }; + 1FC965B1F11B45F98051C565 /* ObjFileImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileImporter.h; path = code/ObjFileImporter.h; sourceTree = SOURCE_ROOT; }; + 21B797DAB0E0427C9339AE0F /* MakeVerboseFormat.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MakeVerboseFormat.cpp; path = code/MakeVerboseFormat.cpp; sourceTree = SOURCE_ROOT; }; + 21E21BE7CB364AC3AB81E54C /* MD2FileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD2FileData.h; path = code/MD2FileData.h; sourceTree = SOURCE_ROOT; }; + 23097CBD64E343738B8F22EE /* BlobIOSystem.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlobIOSystem.h; path = code/BlobIOSystem.h; sourceTree = SOURCE_ROOT; }; + 262DFE65C6D34442AA79D15A /* qnan.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = qnan.h; path = code/qnan.h; sourceTree = SOURCE_ROOT; }; + 267A74499024423A86150697 /* cimport.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cimport.h; path = include/assimp/cimport.h; sourceTree = SOURCE_ROOT; }; + 267D593135514108B7DEF072 /* sweep_context.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = sweep_context.h; path = contrib/poly2tri/poly2tri/sweep/sweep_context.h; sourceTree = SOURCE_ROOT; }; + 26BF681530B04B73961997CB /* FBXCompileConfig.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXCompileConfig.h; path = code/FBXCompileConfig.h; sourceTree = SOURCE_ROOT; }; + 27605E75944D41B0B98260A3 /* ASEParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ASEParser.h; path = code/ASEParser.h; sourceTree = SOURCE_ROOT; }; + 278FB5C8BD814F2DAE04A1C7 /* pstdint.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = pstdint.h; path = include/assimp/Compiler/pstdint.h; sourceTree = SOURCE_ROOT; }; + 279D2A482FE9402A8F7EC441 /* quaternion.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = quaternion.h; path = include/assimp/quaternion.h; sourceTree = SOURCE_ROOT; }; + 27F2019E621B4CDA94DD5270 /* UnrealLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = UnrealLoader.h; path = code/UnrealLoader.h; sourceTree = SOURCE_ROOT; }; + 285D1FDA48EC4DD8933B603E /* IFCBoolean.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCBoolean.cpp; path = code/IFCBoolean.cpp; sourceTree = SOURCE_ROOT; }; + 28A938B21261484998F68F4A /* FindInstancesProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FindInstancesProcess.h; path = code/FindInstancesProcess.h; sourceTree = SOURCE_ROOT; }; + 296407DE471C4F298742FB59 /* StandardShapes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StandardShapes.h; path = code/StandardShapes.h; sourceTree = SOURCE_ROOT; }; + 2ABBB4561E72413EB40702C3 /* ComputeUVMappingProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ComputeUVMappingProcess.cpp; path = code/ComputeUVMappingProcess.cpp; sourceTree = SOURCE_ROOT; }; + 2AC344FBB0C34D49800F4B8A /* GenVertexNormalsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = GenVertexNormalsProcess.h; path = code/GenVertexNormalsProcess.h; sourceTree = SOURCE_ROOT; }; + 2ACC87E846AE4E4A86E1AEF4 /* OptimizeMeshes.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OptimizeMeshes.cpp; path = code/OptimizeMeshes.cpp; sourceTree = SOURCE_ROOT; }; + 2BE34AF1CE0C4767ACE21597 /* IFCLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFCLoader.h; path = code/IFCLoader.h; sourceTree = SOURCE_ROOT; }; + 2C4D504725E540109530E254 /* PlyParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PlyParser.cpp; path = code/PlyParser.cpp; sourceTree = SOURCE_ROOT; }; + 2DCF6F156A3A4B4C807E5368 /* SmoothingGroups.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SmoothingGroups.h; path = code/SmoothingGroups.h; sourceTree = SOURCE_ROOT; }; + 2E7FD92FFCF441B0A60FC8B4 /* IFCCurve.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCCurve.cpp; path = code/IFCCurve.cpp; sourceTree = SOURCE_ROOT; }; + 2F34A6A3C4104625A52BF7C2 /* cexport.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cexport.h; path = include/assimp/cexport.h; sourceTree = SOURCE_ROOT; }; + 3106D75C13874F5AB3EBBFE7 /* BlenderModifier.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderModifier.cpp; path = code/BlenderModifier.cpp; sourceTree = SOURCE_ROOT; }; + 32170F499DAC4E4595AF6D6B /* BaseImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BaseImporter.h; path = code/BaseImporter.h; sourceTree = SOURCE_ROOT; }; + 3267EBBA6EEB435F83FF25E4 /* IFCGeometry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCGeometry.cpp; path = code/IFCGeometry.cpp; sourceTree = SOURCE_ROOT; }; + 32CC68350B7640ACA7C83DDA /* DefaultIOStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DefaultIOStream.h; path = code/DefaultIOStream.h; sourceTree = SOURCE_ROOT; }; + 333F4676A92043739F5A9D32 /* ObjFileParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileParser.h; path = code/ObjFileParser.h; sourceTree = SOURCE_ROOT; }; + 339E56B5FD264481BBF21835 /* CInterfaceIOWrapper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CInterfaceIOWrapper.h; path = code/CInterfaceIOWrapper.h; sourceTree = SOURCE_ROOT; }; + 33B70115CA54405F895BA471 /* FBXNodeAttribute.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXNodeAttribute.cpp; path = code/FBXNodeAttribute.cpp; sourceTree = SOURCE_ROOT; }; + 3551D90CCED1454A8B912066 /* XFileParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileParser.h; path = code/XFileParser.h; sourceTree = SOURCE_ROOT; }; + 35A9B50143214C63A956FA27 /* ConvertToLHProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ConvertToLHProcess.h; path = code/ConvertToLHProcess.h; sourceTree = SOURCE_ROOT; }; + 35E4944C052A4C91BF31DE5F /* MDCLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MDCLoader.cpp; path = code/MDCLoader.cpp; sourceTree = SOURCE_ROOT; }; + 37A3E0E2BB484DD8B9FCCA5E /* NDOLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = NDOLoader.h; path = code/NDOLoader.h; sourceTree = SOURCE_ROOT; }; + 3ACFF3FC39C74C4A966C0FEA /* GenericProperty.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = GenericProperty.h; path = code/GenericProperty.h; sourceTree = SOURCE_ROOT; }; + 3B407EAF162843CBA46BC9D4 /* scene.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = scene.h; path = include/assimp/scene.h; sourceTree = SOURCE_ROOT; }; + 3B8FD96D46314ACD8F157AC3 /* UnrealLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = UnrealLoader.cpp; path = code/UnrealLoader.cpp; sourceTree = SOURCE_ROOT; }; + 3E84DEFC1E0646AD82F79998 /* shared_ptr.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = shared_ptr.hpp; path = code/BoostWorkaround/boost/shared_ptr.hpp; sourceTree = SOURCE_ROOT; }; + 3F5D1E6368384D429BA29D5A /* IFCReaderGen.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCReaderGen.cpp; path = code/IFCReaderGen.cpp; sourceTree = SOURCE_ROOT; }; + 409C98EE093C499B8A574CA9 /* PlyLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PlyLoader.cpp; path = code/PlyLoader.cpp; sourceTree = SOURCE_ROOT; }; + 4108529663904025B21E526B /* ObjFileMtlImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjFileMtlImporter.cpp; path = code/ObjFileMtlImporter.cpp; sourceTree = SOURCE_ROOT; }; + 41C2F6D564924BF4ACE75CAC /* postprocess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = postprocess.h; path = include/assimp/postprocess.h; sourceTree = SOURCE_ROOT; }; + 420D77ED33554D54AA4D50EF /* ColladaParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ColladaParser.cpp; path = code/ColladaParser.cpp; sourceTree = SOURCE_ROOT; }; + 42E110B9E6924AF9B55AE65A /* FBXMeshGeometry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXMeshGeometry.cpp; path = code/FBXMeshGeometry.cpp; sourceTree = SOURCE_ROOT; }; + 42E68041B1C442E3B49FC304 /* B3DImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = B3DImporter.h; path = code/B3DImporter.h; sourceTree = SOURCE_ROOT; }; + 435DC362E63D4CCBA68656D3 /* XFileExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XFileExporter.cpp; path = code/XFileExporter.cpp; sourceTree = SOURCE_ROOT; }; + 43899EB0B0704A9DB8F0C54F /* BlenderDNA.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = BlenderDNA.inl; path = code/BlenderDNA.inl; sourceTree = SOURCE_ROOT; }; + 43ABFF591F374920A5E18A24 /* HMPLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = HMPLoader.cpp; path = code/HMPLoader.cpp; sourceTree = SOURCE_ROOT; }; + 43C75175738C4119871E8BB0 /* Q3BSPZipArchive.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3BSPZipArchive.cpp; path = code/Q3BSPZipArchive.cpp; sourceTree = SOURCE_ROOT; }; + 43FC808D2F4745ACB06A9D33 /* MD5Parser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD5Parser.h; path = code/MD5Parser.h; sourceTree = SOURCE_ROOT; }; + 445F70426FCC42F088405E86 /* COBLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = COBLoader.h; path = code/COBLoader.h; sourceTree = SOURCE_ROOT; }; + 4493838DDEE841BF96A0F008 /* matrix4x4.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = matrix4x4.inl; path = include/assimp/matrix4x4.inl; sourceTree = SOURCE_ROOT; }; + 4568875B66584E12AA1538C7 /* BlenderBMesh.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderBMesh.h; path = code/BlenderBMesh.h; sourceTree = SOURCE_ROOT; }; + 45BC2EB74251493CBBFAEB5D /* SkeletonMeshBuilder.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SkeletonMeshBuilder.h; path = code/SkeletonMeshBuilder.h; sourceTree = SOURCE_ROOT; }; + 45E342A1499E4F03ADD49028 /* BVHLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BVHLoader.h; path = code/BVHLoader.h; sourceTree = SOURCE_ROOT; }; + 45F6A2B351AB4B749E55B299 /* PlyParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PlyParser.h; path = code/PlyParser.h; sourceTree = SOURCE_ROOT; }; + 466D6B9A7CCD402D9AA87071 /* DXFLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DXFLoader.cpp; path = code/DXFLoader.cpp; sourceTree = SOURCE_ROOT; }; + 46E9F455A3284DB399986293 /* IFCProfile.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCProfile.cpp; path = code/IFCProfile.cpp; sourceTree = SOURCE_ROOT; }; + 4770D6DCA1854B4F9B85546A /* DeboneProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DeboneProcess.h; path = code/DeboneProcess.h; sourceTree = SOURCE_ROOT; }; + 47FF3063906E4786ABF0939B /* STEPFile.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STEPFile.h; path = code/STEPFile.h; sourceTree = SOURCE_ROOT; }; + 4866DA5A7BFD49F79B61CBF8 /* TerragenLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TerragenLoader.cpp; path = code/TerragenLoader.cpp; sourceTree = SOURCE_ROOT; }; + 4936396409984881858E7B15 /* irrTypes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrTypes.h; path = contrib/irrXML/irrTypes.h; sourceTree = SOURCE_ROOT; }; + 49AFF879142C4BA4865843DC /* Bitmap.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Bitmap.h; path = code/Bitmap.h; sourceTree = SOURCE_ROOT; }; + 49B655CCE1314D4E8A94B371 /* MD2Loader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD2Loader.cpp; path = code/MD2Loader.cpp; sourceTree = SOURCE_ROOT; }; + 49E993CD86A346869AF473BC /* sweep.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = sweep.cc; path = contrib/poly2tri/poly2tri/sweep/sweep.cc; sourceTree = SOURCE_ROOT; }; + 49FE5C30FC854A3EBD0E9C19 /* irrArray.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrArray.h; path = contrib/irrXML/irrArray.h; sourceTree = SOURCE_ROOT; }; + 4A60A00727F04E049CF3AE33 /* Q3BSPFileParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3BSPFileParser.cpp; path = code/Q3BSPFileParser.cpp; sourceTree = SOURCE_ROOT; }; + 4B571231CE2B464BBF1E853F /* FindDegenerates.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FindDegenerates.h; path = code/FindDegenerates.h; sourceTree = SOURCE_ROOT; }; + 4BBDEB63CFEB4F2EAA95358D /* Subdivision.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Subdivision.cpp; path = code/Subdivision.cpp; sourceTree = SOURCE_ROOT; }; + 4CBC1122A79D4F6C94E36CE3 /* StdOStreamLogStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StdOStreamLogStream.h; path = code/StdOStreamLogStream.h; sourceTree = SOURCE_ROOT; }; + 4D2F1605B9484B08BB33402D /* STLLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STLLoader.cpp; path = code/STLLoader.cpp; sourceTree = SOURCE_ROOT; }; + 4D82A29A8BBF44E69E026F84 /* importerdesc.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = importerdesc.h; path = include/assimp/importerdesc.h; sourceTree = SOURCE_ROOT; }; + 4DABF3CB245F4246B0184513 /* ACLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ACLoader.h; path = code/ACLoader.h; sourceTree = SOURCE_ROOT; }; + 4FE1E4726B144AD1B922A1A0 /* ScenePreprocessor.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ScenePreprocessor.h; path = code/ScenePreprocessor.h; sourceTree = SOURCE_ROOT; }; + 501B18C2B590455D8A3C3E78 /* XGLLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XGLLoader.h; path = code/XGLLoader.h; sourceTree = SOURCE_ROOT; }; + 50935A81362041BEADF18609 /* utils.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = utils.h; path = contrib/poly2tri/poly2tri/common/utils.h; sourceTree = SOURCE_ROOT; }; + 52836A0629E24447B924750A /* SGSpatialSort.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SGSpatialSort.cpp; path = code/SGSpatialSort.cpp; sourceTree = SOURCE_ROOT; }; + 531FBC4210644C61954EA4C4 /* MD2Loader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD2Loader.h; path = code/MD2Loader.h; sourceTree = SOURCE_ROOT; }; + 53537D08E9B44A25B43B697B /* XFileImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileImporter.h; path = code/XFileImporter.h; sourceTree = SOURCE_ROOT; }; + 5631CE86F56F458EA0E2415F /* HMPLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = HMPLoader.h; path = code/HMPLoader.h; sourceTree = SOURCE_ROOT; }; + 563FBACCFD774BDEA4AEAC10 /* MD3Loader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD3Loader.cpp; path = code/MD3Loader.cpp; sourceTree = SOURCE_ROOT; }; + 56ADEC4899C047F2839AD791 /* OgreBinarySerializer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreBinarySerializer.cpp; path = code/OgreBinarySerializer.cpp; sourceTree = SOURCE_ROOT; }; + 56CE07D64D114C4BAB6D9F08 /* Logger.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = Logger.hpp; path = include/assimp/Logger.hpp; sourceTree = SOURCE_ROOT; }; + 56DA1CDC223747F4AFBAF953 /* types.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = types.h; path = include/assimp/types.h; sourceTree = SOURCE_ROOT; }; + 59A1859480754E90B958CA85 /* BlenderTessellator.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderTessellator.h; path = code/BlenderTessellator.h; sourceTree = SOURCE_ROOT; }; + 59E3D32E3FC7438DB148537F /* IFCUtil.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCUtil.cpp; path = code/IFCUtil.cpp; sourceTree = SOURCE_ROOT; }; + 59F8A11A7AED45CC94CEDF28 /* clipper.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = clipper.cpp; path = contrib/clipper/clipper.cpp; sourceTree = SOURCE_ROOT; }; + 5A4E05386C094B809A315A07 /* LWOLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOLoader.cpp; path = code/LWOLoader.cpp; sourceTree = SOURCE_ROOT; }; + 5C15EEB253204E8A8E0D0E38 /* Q3BSPFileParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPFileParser.h; path = code/Q3BSPFileParser.h; sourceTree = SOURCE_ROOT; }; + 5C1EA03E3AE24AA5A778B7F1 /* Profiler.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Profiler.h; path = code/Profiler.h; sourceTree = SOURCE_ROOT; }; + 5D4E64EABD9548A59E9637AF /* irrString.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrString.h; path = contrib/irrXML/irrString.h; sourceTree = SOURCE_ROOT; }; + 5E10483FBE6D4F4594B460E0 /* sweep_context.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = sweep_context.cc; path = contrib/poly2tri/poly2tri/sweep/sweep_context.cc; sourceTree = SOURCE_ROOT; }; + 5F373DF3B03B4B848B78EAD2 /* FBXParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXParser.cpp; path = code/FBXParser.cpp; sourceTree = SOURCE_ROOT; }; + 5F84BDD0D5D345A2BF1E08E1 /* metadata.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = metadata.h; path = include/assimp/metadata.h; sourceTree = SOURCE_ROOT; }; + 5FBE72DCC6AC485ABCF89B8C /* ImproveCacheLocality.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ImproveCacheLocality.h; path = code/ImproveCacheLocality.h; sourceTree = SOURCE_ROOT; }; + 603AFA882AFF49AEAC2C8FA2 /* BlenderBMesh.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderBMesh.cpp; path = code/BlenderBMesh.cpp; sourceTree = SOURCE_ROOT; }; + 6162B57DE81A4E538430056E /* IFCReaderGen.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFCReaderGen.h; path = code/IFCReaderGen.h; sourceTree = SOURCE_ROOT; }; + 621E96E95F60421EB6B4525C /* MDCLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDCLoader.h; path = code/MDCLoader.h; sourceTree = SOURCE_ROOT; }; + 62E8551653634972ABBABCAD /* sweep.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = sweep.h; path = contrib/poly2tri/poly2tri/sweep/sweep.h; sourceTree = SOURCE_ROOT; }; + 6347FA5D391D4320B9457D3F /* MS3DLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MS3DLoader.h; path = code/MS3DLoader.h; sourceTree = SOURCE_ROOT; }; + 6389F68312384CFD847B1D13 /* AssbinExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssbinExporter.cpp; path = code/AssbinExporter.cpp; sourceTree = SOURCE_ROOT; }; + 638B3F6AC17A435C9B86C86C /* ColladaExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaExporter.h; path = code/ColladaExporter.h; sourceTree = SOURCE_ROOT; }; + 6454A961FAF44B3E9086D2F8 /* Q3BSPZipArchive.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPZipArchive.h; path = code/Q3BSPZipArchive.h; sourceTree = SOURCE_ROOT; }; + 64C6BACDA5DD4139AA26EE81 /* irrXML.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = irrXML.cpp; path = contrib/irrXML/irrXML.cpp; sourceTree = SOURCE_ROOT; }; + 657B9A15EE7A4B7BA519A969 /* LogStream.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = LogStream.hpp; path = include/assimp/LogStream.hpp; sourceTree = SOURCE_ROOT; }; + 670FE6DD7EDF421488F2F97F /* IRRMeshLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IRRMeshLoader.h; path = code/IRRMeshLoader.h; sourceTree = SOURCE_ROOT; }; + 680C392FFE0B4CC5ABC7CA64 /* LWOAnimation.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOAnimation.cpp; path = code/LWOAnimation.cpp; sourceTree = SOURCE_ROOT; }; + 680FBD79376A41B690C405B8 /* LineSplitter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LineSplitter.h; path = code/LineSplitter.h; sourceTree = SOURCE_ROOT; }; + 68703F99581F49CB9E2B9F37 /* LWSLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWSLoader.h; path = code/LWSLoader.h; sourceTree = SOURCE_ROOT; }; + 6981B16018CF46CAA54C0BAA /* ColladaLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaLoader.h; path = code/ColladaLoader.h; sourceTree = SOURCE_ROOT; }; + 69AFF47737244CE3BD1653CC /* ProgressHandler.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = ProgressHandler.hpp; path = include/assimp/ProgressHandler.hpp; sourceTree = SOURCE_ROOT; }; + 6A86069DEEDC42B88634F78D /* RemoveComments.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RemoveComments.cpp; path = code/RemoveComments.cpp; sourceTree = SOURCE_ROOT; }; + 6AC645CEB6F74AE5A62DF68B /* IFF.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFF.h; path = code/IFF.h; sourceTree = SOURCE_ROOT; }; + 6BAB32C8E06E43689FC5E7EA /* MD5Loader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD5Loader.h; path = code/MD5Loader.h; sourceTree = SOURCE_ROOT; }; + 6CC21F1D0E4140FE923E4EE6 /* AssbinExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = AssbinExporter.h; path = code/AssbinExporter.h; sourceTree = SOURCE_ROOT; }; + 6D72952403D04713A6451654 /* vector3.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = vector3.h; path = include/assimp/vector3.h; sourceTree = SOURCE_ROOT; }; + 6E20FCC571F144DDBD831CCB /* DeboneProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DeboneProcess.cpp; path = code/DeboneProcess.cpp; sourceTree = SOURCE_ROOT; }; + 6E82409E9D274D278971F3B0 /* Q3BSPFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPFileData.h; path = code/Q3BSPFileData.h; sourceTree = SOURCE_ROOT; }; + 6F49958B5CCF423681133515 /* OgreParsingUtils.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreParsingUtils.h; path = code/OgreParsingUtils.h; sourceTree = SOURCE_ROOT; }; + 6F65B6129F774AEDB8DC845A /* TargetAnimation.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TargetAnimation.cpp; path = code/TargetAnimation.cpp; sourceTree = SOURCE_ROOT; }; + 6F88E78E61FC4A01BC30BE85 /* ConvertUTF.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ConvertUTF.h; path = contrib/ConvertUTF/ConvertUTF.h; sourceTree = SOURCE_ROOT; }; + 705D30EE141A48F292783F0E /* Assimp.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Assimp.cpp; path = code/Assimp.cpp; sourceTree = SOURCE_ROOT; }; + 70D5FDFA995E45E6A3E8FD37 /* ImproveCacheLocality.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ImproveCacheLocality.cpp; path = code/ImproveCacheLocality.cpp; sourceTree = SOURCE_ROOT; }; + 71EAFDE1910B4A54AAAF2101 /* HMPFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = HMPFileData.h; path = code/HMPFileData.h; sourceTree = SOURCE_ROOT; }; + 71F65BF6936E4E97A5933EF9 /* OgreImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreImporter.h; path = code/OgreImporter.h; sourceTree = SOURCE_ROOT; }; + 725DAD1CE04C4F64BDAB7037 /* ValidateDataStructure.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ValidateDataStructure.h; path = code/ValidateDataStructure.h; sourceTree = SOURCE_ROOT; }; + 72832410F47C44E3BAE709C2 /* BlenderDNA.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderDNA.h; path = code/BlenderDNA.h; sourceTree = SOURCE_ROOT; }; + 72F2DF0B93CF4D3ABAD7513D /* LWOLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWOLoader.h; path = code/LWOLoader.h; sourceTree = SOURCE_ROOT; }; + 72F637AC7D9E4FBFBB9201CE /* ioapi.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ioapi.h; path = contrib/unzip/ioapi.h; sourceTree = SOURCE_ROOT; }; + 731205CAB88247C095E33412 /* Exporter.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = Exporter.hpp; path = include/assimp/Exporter.hpp; sourceTree = SOURCE_ROOT; }; + 73A3D87FF2C04C3BA3684F54 /* SceneCombiner.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SceneCombiner.cpp; path = code/SceneCombiner.cpp; sourceTree = SOURCE_ROOT; }; + 74679D2078FD46ED9AC73355 /* IFCOpenings.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCOpenings.cpp; path = code/IFCOpenings.cpp; sourceTree = SOURCE_ROOT; }; + 74C02A113B804568A7E39CBC /* XFileParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XFileParser.cpp; path = code/XFileParser.cpp; sourceTree = SOURCE_ROOT; }; + 7644CE6B26D740258577EE9D /* scoped_ptr.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = scoped_ptr.hpp; path = code/BoostWorkaround/boost/scoped_ptr.hpp; sourceTree = SOURCE_ROOT; }; + 76773A53296549FFA43956A1 /* Q3DLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3DLoader.h; path = code/Q3DLoader.h; sourceTree = SOURCE_ROOT; }; + 76D801D898C4443D8240EDB7 /* BlenderSceneGen.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderSceneGen.h; path = code/BlenderSceneGen.h; sourceTree = SOURCE_ROOT; }; + 77908990BEF04D0881E8AE80 /* CSMLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = CSMLoader.cpp; path = code/CSMLoader.cpp; sourceTree = SOURCE_ROOT; }; + 79A49EFE23E34E1CBA2E4377 /* OgreStructs.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreStructs.cpp; path = code/OgreStructs.cpp; sourceTree = SOURCE_ROOT; }; + 7BDF90B124F74A39A5EB3B02 /* DXFLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DXFLoader.h; path = code/DXFLoader.h; sourceTree = SOURCE_ROOT; }; + 7C10178C0B7241DD874A0AF3 /* ColladaHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaHelper.h; path = code/ColladaHelper.h; sourceTree = SOURCE_ROOT; }; + 7C477FA4D89548F1BCEDC5A0 /* ASELoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ASELoader.cpp; path = code/ASELoader.cpp; sourceTree = SOURCE_ROOT; }; + 7C63156710964DEDAC0929BD /* HalfLifeFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = HalfLifeFileData.h; path = code/HalfLifeFileData.h; sourceTree = SOURCE_ROOT; }; + 7CAF8A3096E04CB983B53CC1 /* BlenderIntermediate.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderIntermediate.h; path = code/BlenderIntermediate.h; sourceTree = SOURCE_ROOT; }; + 7DC4B0B5E57F4F4892CC823E /* MemoryIOWrapper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MemoryIOWrapper.h; path = code/MemoryIOWrapper.h; sourceTree = SOURCE_ROOT; }; + 7E8BA0D338C9433587BC6C35 /* StreamWriter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StreamWriter.h; path = code/StreamWriter.h; sourceTree = SOURCE_ROOT; }; + 7F29EF981AB26C4900E9D380 /* libz.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.dylib; path = /usr/lib/libz.1.dylib; sourceTree = ""; }; + 7F392D921AB2C7BB00D952EB /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "/usr/lib/libc++.dylib"; sourceTree = ""; }; + 7F7922801AB43AC3005A8E5D /* libassimp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libassimp.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 7F7A93A51B65D0110094C4DA /* DDLNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DDLNode.cpp; path = contrib/openddlparser/code/DDLNode.cpp; sourceTree = ""; }; + 7F7A93A61B65D0110094C4DA /* OpenDDLParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenDDLParser.cpp; path = contrib/openddlparser/code/OpenDDLParser.cpp; sourceTree = ""; }; + 7F7A93A71B65D0110094C4DA /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = contrib/openddlparser/code/Value.cpp; sourceTree = ""; }; + 7FBE9FE51B65AC1200D2115E /* OpenGEXExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGEXExporter.cpp; path = code/OpenGEXExporter.cpp; sourceTree = ""; }; + 7FBE9FE61B65AC1200D2115E /* OpenGEXExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGEXExporter.h; path = code/OpenGEXExporter.h; sourceTree = ""; }; + 7FBE9FE71B65AC1200D2115E /* OpenGEXImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGEXImporter.cpp; path = code/OpenGEXImporter.cpp; sourceTree = ""; }; + 7FBE9FE81B65AC1200D2115E /* OpenGEXImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGEXImporter.h; path = code/OpenGEXImporter.h; sourceTree = ""; }; + 7FBE9FE91B65AC1200D2115E /* OpenGEXStructs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGEXStructs.h; path = code/OpenGEXStructs.h; sourceTree = ""; }; + 7FBEA0071B65AF9200D2115E /* DDLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DDLNode.h; path = contrib/openddlparser/include/openddlparser/DDLNode.h; sourceTree = ""; }; + 7FBEA0081B65AF9200D2115E /* OpenDDLCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenDDLCommon.h; path = contrib/openddlparser/include/openddlparser/OpenDDLCommon.h; sourceTree = ""; }; + 7FBEA00A1B65AF9200D2115E /* OpenDDLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenDDLParser.h; path = contrib/openddlparser/include/openddlparser/OpenDDLParser.h; sourceTree = ""; }; + 7FBEA00B1B65AF9200D2115E /* OpenDDLParserUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenDDLParserUtils.h; path = contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h; sourceTree = ""; }; + 7FBEA00D1B65AF9200D2115E /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = contrib/openddlparser/include/openddlparser/Value.h; sourceTree = ""; }; + 7FBEA0111B65B11800D2115E /* Version.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Version.cpp; path = code/Version.cpp; sourceTree = ""; }; + 7FF72CB6E99E40E19AE0E64C /* MaterialSystem.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MaterialSystem.cpp; path = code/MaterialSystem.cpp; sourceTree = SOURCE_ROOT; }; + 815702BED5644DD5B242F347 /* TerragenLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TerragenLoader.h; path = code/TerragenLoader.h; sourceTree = SOURCE_ROOT; }; + 8299401C3E4A43A18E887DC1 /* SGSpatialSort.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SGSpatialSort.h; path = code/SGSpatialSort.h; sourceTree = SOURCE_ROOT; }; + 8343910BBD464297932B3CE0 /* FixNormalsStep.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FixNormalsStep.h; path = code/FixNormalsStep.h; sourceTree = SOURCE_ROOT; }; + 8476FEE874C1404B9B4B9617 /* SceneCombiner.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SceneCombiner.h; path = code/SceneCombiner.h; sourceTree = SOURCE_ROOT; }; + 849EC6315E4A4E5FA06521EA /* cdt.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = cdt.cc; path = contrib/poly2tri/poly2tri/sweep/cdt.cc; sourceTree = SOURCE_ROOT; }; + 862131D4574B4CABA5EC957B /* ObjFileImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjFileImporter.cpp; path = code/ObjFileImporter.cpp; sourceTree = SOURCE_ROOT; }; + 86E296E459F94050ACBA3C63 /* IOSystem.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = IOSystem.hpp; path = include/assimp/IOSystem.hpp; sourceTree = SOURCE_ROOT; }; + 88ADA502481B403191BD35F0 /* STLExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STLExporter.h; path = code/STLExporter.h; sourceTree = SOURCE_ROOT; }; + 890E32C714444692AA016AE5 /* ProcessHelper.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ProcessHelper.cpp; path = code/ProcessHelper.cpp; sourceTree = SOURCE_ROOT; }; + 89473420F7E448A7BE71FCBA /* FBXUtil.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXUtil.h; path = code/FBXUtil.h; sourceTree = SOURCE_ROOT; }; + 89D2D359BD854D8AA60CB720 /* STLExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STLExporter.cpp; path = code/STLExporter.cpp; sourceTree = SOURCE_ROOT; }; + 8C9AEFFFF3B948148D32D76F /* shared_array.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = shared_array.hpp; path = code/BoostWorkaround/boost/shared_array.hpp; sourceTree = SOURCE_ROOT; }; + 8D53CC35AAED4CE8B9710E04 /* vector3.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = vector3.inl; path = include/assimp/vector3.inl; sourceTree = SOURCE_ROOT; }; + 8D977E197CA4477AB9F3278C /* NullLogger.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = NullLogger.hpp; path = include/assimp/NullLogger.hpp; sourceTree = SOURCE_ROOT; }; + 8E2108F568374F65ACE217D1 /* light.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = light.h; path = include/assimp/light.h; sourceTree = SOURCE_ROOT; }; + 8E395349546A4FDF843E6963 /* XGLLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XGLLoader.cpp; path = code/XGLLoader.cpp; sourceTree = SOURCE_ROOT; }; + 8EEC6646FC044D1E9658A590 /* SpatialSort.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SpatialSort.cpp; path = code/SpatialSort.cpp; sourceTree = SOURCE_ROOT; }; + 8F4261792A60481DA04E6E1A /* XFileHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileHelper.h; path = code/XFileHelper.h; sourceTree = SOURCE_ROOT; }; + 8FE8B4781BB3406EB3452154 /* ObjTools.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjTools.h; path = code/ObjTools.h; sourceTree = SOURCE_ROOT; }; + 904A696E49D540C2A880792B /* cdt.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cdt.h; path = contrib/poly2tri/poly2tri/sweep/cdt.h; sourceTree = SOURCE_ROOT; }; + 906F71D342544BF381E1318E /* BlenderLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderLoader.cpp; path = code/BlenderLoader.cpp; sourceTree = SOURCE_ROOT; }; + 90949C7A51E84D3595D71A6B /* config.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = config.h; path = include/assimp/config.h; sourceTree = SOURCE_ROOT; }; + 90DD6CA40A5E41458E11FF3E /* CalcTangentsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = CalcTangentsProcess.cpp; path = code/CalcTangentsProcess.cpp; sourceTree = SOURCE_ROOT; }; + 916456789C75419DB1436FAD /* OgreBinarySerializer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreBinarySerializer.h; path = code/OgreBinarySerializer.h; sourceTree = SOURCE_ROOT; }; + 91D49B3C51684882A01EA492 /* PlyLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PlyLoader.h; path = code/PlyLoader.h; sourceTree = SOURCE_ROOT; }; + 91EF6411C40946758A06144F /* ObjExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjExporter.h; path = code/ObjExporter.h; sourceTree = SOURCE_ROOT; }; + 91FF8B1DCC0644008AE34A04 /* FindInvalidDataProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FindInvalidDataProcess.h; path = code/FindInvalidDataProcess.h; sourceTree = SOURCE_ROOT; }; + 923283A9791E4B4E86D623FC /* OgreImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreImporter.cpp; path = code/OgreImporter.cpp; sourceTree = SOURCE_ROOT; }; + 926E8B7924144B349A88023D /* OptimizeGraph.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OptimizeGraph.h; path = code/OptimizeGraph.h; sourceTree = SOURCE_ROOT; }; + 9293C5A353F9497A850E05D5 /* unzip.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = unzip.h; path = contrib/unzip/unzip.h; sourceTree = SOURCE_ROOT; }; + 929F59CCA32549EC884A5033 /* ASEParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ASEParser.cpp; path = code/ASEParser.cpp; sourceTree = SOURCE_ROOT; }; + 92D8734FFF9742B39A371B70 /* ConvertToLHProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ConvertToLHProcess.cpp; path = code/ConvertToLHProcess.cpp; sourceTree = SOURCE_ROOT; }; + 9472EFB6831740DD91471337 /* Importer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Importer.cpp; path = code/Importer.cpp; sourceTree = SOURCE_ROOT; }; + 95641498F25A4F6FABBC03A4 /* MDCFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDCFileData.h; path = code/MDCFileData.h; sourceTree = SOURCE_ROOT; }; + 957FBC18FED2484F83308E36 /* SpatialSort.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SpatialSort.h; path = code/SpatialSort.h; sourceTree = SOURCE_ROOT; }; + 967D69AC1A344D4E988F0B2C /* common_factor_rt.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = common_factor_rt.hpp; path = code/BoostWorkaround/boost/math/common_factor_rt.hpp; sourceTree = SOURCE_ROOT; }; + 96A02CBA1AE642BD9519719D /* make_shared.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = make_shared.hpp; path = code/BoostWorkaround/boost/make_shared.hpp; sourceTree = SOURCE_ROOT; }; + 973D4231A4AA4925B019FEEE /* unzip.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = unzip.c; path = contrib/unzip/unzip.c; sourceTree = SOURCE_ROOT; }; + 9761D873B9604504B9AD7CD5 /* defs.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = defs.h; path = include/assimp/defs.h; sourceTree = SOURCE_ROOT; }; + 97914BDA4AA34081855BF16C /* ScenePrivate.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ScenePrivate.h; path = code/ScenePrivate.h; sourceTree = SOURCE_ROOT; }; + 97DFA90F9D0C4B999C150B10 /* IRRLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IRRLoader.cpp; path = code/IRRLoader.cpp; sourceTree = SOURCE_ROOT; }; + 97F52051AF4F478FA77AABBC /* quaternion.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = quaternion.inl; path = include/assimp/quaternion.inl; sourceTree = SOURCE_ROOT; }; + 982AE676D2364350B1FBD095 /* GenFaceNormalsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = GenFaceNormalsProcess.cpp; path = code/GenFaceNormalsProcess.cpp; sourceTree = SOURCE_ROOT; }; + 9855496CEA774F4FA7FBB862 /* FBXDeformer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXDeformer.cpp; path = code/FBXDeformer.cpp; sourceTree = SOURCE_ROOT; }; + 99A4349D505F4CC593F48CF6 /* SplitByBoneCountProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SplitByBoneCountProcess.cpp; path = code/SplitByBoneCountProcess.cpp; sourceTree = SOURCE_ROOT; }; + 9A0960F123634603B15EEA38 /* ConvertUTF.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = ConvertUTF.c; path = contrib/ConvertUTF/ConvertUTF.c; sourceTree = SOURCE_ROOT; }; + 9A61AF384D4D45778698DD7D /* ASELoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ASELoader.h; path = code/ASELoader.h; sourceTree = SOURCE_ROOT; }; + 9B2827B3E64147E08A5AD334 /* SkeletonMeshBuilder.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SkeletonMeshBuilder.cpp; path = code/SkeletonMeshBuilder.cpp; sourceTree = SOURCE_ROOT; }; + 9B4221AA0AD2418FAA45EB64 /* FindInvalidDataProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FindInvalidDataProcess.cpp; path = code/FindInvalidDataProcess.cpp; sourceTree = SOURCE_ROOT; }; + 9C5E3F9248B64C7EBF20EC27 /* Hash.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Hash.h; path = code/Hash.h; sourceTree = SOURCE_ROOT; }; + 9D203F78B24C4D7E8E2084A3 /* FBXProperties.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXProperties.cpp; path = code/FBXProperties.cpp; sourceTree = SOURCE_ROOT; }; + 9E0572B45F1F4605BD5C919D /* COBScene.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = COBScene.h; path = code/COBScene.h; sourceTree = SOURCE_ROOT; }; + A06CBE89CFAB48E786F7A5C0 /* 3DSLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = 3DSLoader.h; path = code/3DSLoader.h; sourceTree = SOURCE_ROOT; }; + A0AED12A1A6D4635A8CFB65A /* GenVertexNormalsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = GenVertexNormalsProcess.cpp; path = code/GenVertexNormalsProcess.cpp; sourceTree = SOURCE_ROOT; }; + A14347E954E8413CAF1455EA /* LWOAnimation.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWOAnimation.h; path = code/LWOAnimation.h; sourceTree = SOURCE_ROOT; }; + A1A9535EDF9A4FF2B8DABD7D /* AssimpCExport.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssimpCExport.cpp; path = code/AssimpCExport.cpp; sourceTree = SOURCE_ROOT; }; + A257229A058041389981CFC1 /* XFileExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileExporter.h; path = code/XFileExporter.h; sourceTree = SOURCE_ROOT; }; + A277DBC1EFB944F995659A20 /* MD5Loader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD5Loader.cpp; path = code/MD5Loader.cpp; sourceTree = SOURCE_ROOT; }; + A3D3024C3A59423487A125C8 /* STEPFileReader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STEPFileReader.h; path = code/STEPFileReader.h; sourceTree = SOURCE_ROOT; }; + A43641DC9C1B4B578BC40476 /* SplitLargeMeshes.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SplitLargeMeshes.cpp; path = code/SplitLargeMeshes.cpp; sourceTree = SOURCE_ROOT; }; + A436C47FBF904FECB4A58462 /* ProcessHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ProcessHelper.h; path = code/ProcessHelper.h; sourceTree = SOURCE_ROOT; }; + A4CBF9157F01460ABEDEBF28 /* crypt.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = crypt.h; path = contrib/unzip/crypt.h; sourceTree = SOURCE_ROOT; }; + A58410FEAA884A2D8D73ACCE /* BaseImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BaseImporter.cpp; path = code/BaseImporter.cpp; sourceTree = SOURCE_ROOT; }; + A72115ED828F4069A427B460 /* Subdivision.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Subdivision.h; path = code/Subdivision.h; sourceTree = SOURCE_ROOT; }; + A7733823362B4A389102D177 /* TargetAnimation.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TargetAnimation.h; path = code/TargetAnimation.h; sourceTree = SOURCE_ROOT; }; + A7A56A688A3845768410F500 /* FBXConverter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXConverter.cpp; path = code/FBXConverter.cpp; sourceTree = SOURCE_ROOT; }; + A7A86F81858F4D928A568E17 /* FBXConverter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXConverter.h; path = code/FBXConverter.h; sourceTree = SOURCE_ROOT; }; + A7A990C6FF244DC397B7BA7C /* MS3DLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MS3DLoader.cpp; path = code/MS3DLoader.cpp; sourceTree = SOURCE_ROOT; }; + A7CEBC6894424B888326CAB2 /* tuple.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = tuple.hpp; path = code/BoostWorkaround/boost/tuple/tuple.hpp; sourceTree = SOURCE_ROOT; }; + A88D56FBEA084A3EA9A0ECB3 /* Q3BSPFileImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3BSPFileImporter.cpp; path = code/Q3BSPFileImporter.cpp; sourceTree = SOURCE_ROOT; }; + A9E9EB834E09420197C3FB8C /* DefaultLogger.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DefaultLogger.cpp; path = code/DefaultLogger.cpp; sourceTree = SOURCE_ROOT; }; + AA4946AEDB9F4F22873C4C4F /* FBXImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXImporter.h; path = code/FBXImporter.h; sourceTree = SOURCE_ROOT; }; + AA92FFC8B06D4569AD9C4CB1 /* MDLLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MDLLoader.cpp; path = code/MDLLoader.cpp; sourceTree = SOURCE_ROOT; }; + AAB9AE5328F843F5A8A3E85C /* OptimizeGraph.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OptimizeGraph.cpp; path = code/OptimizeGraph.cpp; sourceTree = SOURCE_ROOT; }; + AAD3EA9B0BB84A788FCCA83E /* foreach.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = foreach.hpp; path = code/BoostWorkaround/boost/foreach.hpp; sourceTree = SOURCE_ROOT; }; + ABDA70358E34432A8A4637F4 /* RemoveVCProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RemoveVCProcess.h; path = code/RemoveVCProcess.h; sourceTree = SOURCE_ROOT; }; + AC699876B6364EC1878CBA44 /* OgreXmlSerializer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreXmlSerializer.h; path = code/OgreXmlSerializer.h; sourceTree = SOURCE_ROOT; }; + ACF73EEAB2424213BF7158D5 /* ObjFileParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjFileParser.cpp; path = code/ObjFileParser.cpp; sourceTree = SOURCE_ROOT; }; + AD969BA482564C7FAA372F7C /* RemoveRedundantMaterials.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RemoveRedundantMaterials.h; path = code/RemoveRedundantMaterials.h; sourceTree = SOURCE_ROOT; }; + ADACEBC4973F4FC0A6FEC68A /* RemoveRedundantMaterials.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RemoveRedundantMaterials.cpp; path = code/RemoveRedundantMaterials.cpp; sourceTree = SOURCE_ROOT; }; + AE00939F150F413780C8AAD7 /* shapes.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = shapes.cc; path = contrib/poly2tri/poly2tri/common/shapes.cc; sourceTree = SOURCE_ROOT; }; + AE1C2E2C9C424B3684AD9D4A /* texture.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = texture.h; path = include/assimp/texture.h; sourceTree = SOURCE_ROOT; }; + AF75E6049338489BB256D295 /* ioapi.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = ioapi.c; path = contrib/unzip/ioapi.c; sourceTree = SOURCE_ROOT; }; + AFA8B6DE5B3A4E52A85041C9 /* LWOFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWOFileData.h; path = code/LWOFileData.h; sourceTree = SOURCE_ROOT; }; + AFF41974881F466A9561BE4B /* LWSLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWSLoader.cpp; path = code/LWSLoader.cpp; sourceTree = SOURCE_ROOT; }; + B04FE3598E344EC09B59CA2F /* IRRShared.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IRRShared.h; path = code/IRRShared.h; sourceTree = SOURCE_ROOT; }; + B05DC38593F04180B322360B /* camera.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = camera.h; path = include/assimp/camera.h; sourceTree = SOURCE_ROOT; }; + B211101B342C414A9E43B7BC /* SplitByBoneCountProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SplitByBoneCountProcess.h; path = code/SplitByBoneCountProcess.h; sourceTree = SOURCE_ROOT; }; + B36DA471B9E142FC9425EC45 /* JoinVerticesProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = JoinVerticesProcess.cpp; path = code/JoinVerticesProcess.cpp; sourceTree = SOURCE_ROOT; }; + B3E8A1BEF8E74F04AE06871B /* AssxmlExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssxmlExporter.cpp; path = code/AssxmlExporter.cpp; sourceTree = SOURCE_ROOT; }; + B4086213AE40445F817FA840 /* RemoveComments.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RemoveComments.h; path = code/RemoveComments.h; sourceTree = SOURCE_ROOT; }; + B40FE1BF9D8E411493BBDE0C /* ComputeUVMappingProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ComputeUVMappingProcess.h; path = code/ComputeUVMappingProcess.h; sourceTree = SOURCE_ROOT; }; + B441D87EE6ED4EBFB0586B66 /* anim.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = anim.h; path = include/assimp/anim.h; sourceTree = SOURCE_ROOT; }; + B4C688FA08F44716855CDD3C /* FBXImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXImporter.cpp; path = code/FBXImporter.cpp; sourceTree = SOURCE_ROOT; }; + B4F1B5789CA540C78FB9219D /* NDOLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = NDOLoader.cpp; path = code/NDOLoader.cpp; sourceTree = SOURCE_ROOT; }; + B522B83A39CA461CBCABE25A /* BlenderScene.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderScene.h; path = code/BlenderScene.h; sourceTree = SOURCE_ROOT; }; + B54FBAAF061B40DBA3F48F83 /* IOStream.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = IOStream.hpp; path = include/assimp/IOStream.hpp; sourceTree = SOURCE_ROOT; }; + B6074B1E864740F787A97EA3 /* vector2.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = vector2.inl; path = include/assimp/vector2.inl; sourceTree = SOURCE_ROOT; }; + B65258E349704523BC43904D /* BlenderDNA.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderDNA.cpp; path = code/BlenderDNA.cpp; sourceTree = SOURCE_ROOT; }; + B6982D8069A145E5B9F97684 /* DXFHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DXFHelper.h; path = code/DXFHelper.h; sourceTree = SOURCE_ROOT; }; + B7192C50B16142398B7CD221 /* DefaultProgressHandler.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DefaultProgressHandler.h; path = code/DefaultProgressHandler.h; sourceTree = SOURCE_ROOT; }; + B72D0BA3EF66439F8D582ED3 /* advancing_front.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = advancing_front.cc; path = contrib/poly2tri/poly2tri/sweep/advancing_front.cc; sourceTree = SOURCE_ROOT; }; + B9DFF24FD63A4D9FAE213EED /* Importer.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = Importer.hpp; path = include/assimp/Importer.hpp; sourceTree = SOURCE_ROOT; }; + BA832069DF214327AE067503 /* matrix4x4.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = matrix4x4.h; path = include/assimp/matrix4x4.h; sourceTree = SOURCE_ROOT; }; + BABB7734139C452A9DDEE797 /* FindDegenerates.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FindDegenerates.cpp; path = code/FindDegenerates.cpp; sourceTree = SOURCE_ROOT; }; + BB38E7E7661842448F008372 /* FBXDocumentUtil.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXDocumentUtil.cpp; path = code/FBXDocumentUtil.cpp; sourceTree = SOURCE_ROOT; }; + BBEE1CF81183473C8492FC03 /* CalcTangentsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CalcTangentsProcess.h; path = code/CalcTangentsProcess.h; sourceTree = SOURCE_ROOT; }; + BD9A81E0E27E44718609615B /* SortByPTypeProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SortByPTypeProcess.cpp; path = code/SortByPTypeProcess.cpp; sourceTree = SOURCE_ROOT; }; + BDD30C77BB68497EA3B7F2F7 /* StringComparison.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StringComparison.h; path = code/StringComparison.h; sourceTree = SOURCE_ROOT; }; + BF94F50C216B45388CDEC1EF /* OFFLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OFFLoader.h; path = code/OFFLoader.h; sourceTree = SOURCE_ROOT; }; + C17C5037C995420C8D259C0C /* FBXImportSettings.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXImportSettings.h; path = code/FBXImportSettings.h; sourceTree = SOURCE_ROOT; }; + C18C5023460E4D17B8C922D7 /* StandardShapes.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = StandardShapes.cpp; path = code/StandardShapes.cpp; sourceTree = SOURCE_ROOT; }; + C2C9EAC9B5B74AC397B070E8 /* scoped_array.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = scoped_array.hpp; path = code/BoostWorkaround/boost/scoped_array.hpp; sourceTree = SOURCE_ROOT; }; + C490BBF1881240EEA4A96315 /* clipper.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = clipper.hpp; path = contrib/clipper/clipper.hpp; sourceTree = SOURCE_ROOT; }; + C5178B3983F147F3B9BD8217 /* Q3DLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3DLoader.cpp; path = code/Q3DLoader.cpp; sourceTree = SOURCE_ROOT; }; + C54518F708BA4A328D5D7325 /* FixNormalsStep.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FixNormalsStep.cpp; path = code/FixNormalsStep.cpp; sourceTree = SOURCE_ROOT; }; + C582480917FF4EB09C164D70 /* SMDLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SMDLoader.h; path = code/SMDLoader.h; sourceTree = SOURCE_ROOT; }; + C5C3ED2BE50D4684994BD533 /* TextureTransform.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TextureTransform.h; path = code/TextureTransform.h; sourceTree = SOURCE_ROOT; }; + C6D3C3E2BA2F49F2B17E7580 /* STLLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STLLoader.h; path = code/STLLoader.h; sourceTree = SOURCE_ROOT; }; + C7B37CA474DF4CE7A5B0658E /* ai_assert.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ai_assert.h; path = include/assimp/ai_assert.h; sourceTree = SOURCE_ROOT; }; + C80B9A3AF4204AE08AA50BAE /* BVHLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BVHLoader.cpp; path = code/BVHLoader.cpp; sourceTree = SOURCE_ROOT; }; + C84DA0E6CE13493D833BA1C1 /* COBLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = COBLoader.cpp; path = code/COBLoader.cpp; sourceTree = SOURCE_ROOT; }; + C9A101D1311C4E77AAEDD94C /* FindInstancesProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FindInstancesProcess.cpp; path = code/FindInstancesProcess.cpp; sourceTree = SOURCE_ROOT; }; + CB042D863BD447FFB117AE34 /* 3DSHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = 3DSHelper.h; path = code/3DSHelper.h; sourceTree = SOURCE_ROOT; }; + CC54A231FF6B4B0CABCFD167 /* IRRShared.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IRRShared.cpp; path = code/IRRShared.cpp; sourceTree = SOURCE_ROOT; }; + CC5D5CA1789448E9869B9669 /* PlyExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PlyExporter.h; path = code/PlyExporter.h; sourceTree = SOURCE_ROOT; }; + CDE3ECA98173418A9F997992 /* STEPFileReader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STEPFileReader.cpp; path = code/STEPFileReader.cpp; sourceTree = SOURCE_ROOT; }; + CEC69808E1844C23B95D3475 /* MDLMaterialLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MDLMaterialLoader.cpp; path = code/MDLMaterialLoader.cpp; sourceTree = SOURCE_ROOT; }; + CF07D05DC86F4C98BC42FDCF /* FBXTokenizer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXTokenizer.cpp; path = code/FBXTokenizer.cpp; sourceTree = SOURCE_ROOT; }; + D029CE902F8045B0B3AFFDDB /* ImporterRegistry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ImporterRegistry.cpp; path = code/ImporterRegistry.cpp; sourceTree = SOURCE_ROOT; }; + D0E9BB0220704C5D93CE7CE9 /* IFCLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCLoader.cpp; path = code/IFCLoader.cpp; sourceTree = SOURCE_ROOT; }; + D1073FF20359469D921C9316 /* irrXMLWrapper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrXMLWrapper.h; path = code/irrXMLWrapper.h; sourceTree = SOURCE_ROOT; }; + D2869C6AD4814588A45E8F81 /* NFFLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = NFFLoader.h; path = code/NFFLoader.h; sourceTree = SOURCE_ROOT; }; + D2EEB62ECBF749AA89146C66 /* SplitLargeMeshes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SplitLargeMeshes.h; path = code/SplitLargeMeshes.h; sourceTree = SOURCE_ROOT; }; + D40F70AC841D4B788B5C696B /* CXMLReaderImpl.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CXMLReaderImpl.h; path = contrib/irrXML/CXMLReaderImpl.h; sourceTree = SOURCE_ROOT; }; + D56A4C70F65D4E07BD792D2C /* STEPFileEncoding.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STEPFileEncoding.h; path = code/STEPFileEncoding.h; sourceTree = SOURCE_ROOT; }; + D5F4108F03D7457EB641836B /* MDLFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDLFileData.h; path = code/MDLFileData.h; sourceTree = SOURCE_ROOT; }; + D629F6BF53864979B7619067 /* LWOBLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOBLoader.cpp; path = code/LWOBLoader.cpp; sourceTree = SOURCE_ROOT; }; + D82B5BA87B184532BE74D24F /* LogAux.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LogAux.h; path = code/LogAux.h; sourceTree = SOURCE_ROOT; }; + D958B0B445E64F4BA9145D82 /* DefaultLogger.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = DefaultLogger.hpp; path = include/assimp/DefaultLogger.hpp; sourceTree = SOURCE_ROOT; }; + D9AB66BD27E246A18091626F /* DefaultIOSystem.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DefaultIOSystem.h; path = code/DefaultIOSystem.h; sourceTree = SOURCE_ROOT; }; + D9FEEF58B24548F782A5D53C /* AssbinLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssbinLoader.cpp; path = code/AssbinLoader.cpp; sourceTree = SOURCE_ROOT; }; + DAE82F651F9E4D91A6A6C753 /* advancing_front.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = advancing_front.h; path = contrib/poly2tri/poly2tri/sweep/advancing_front.h; sourceTree = SOURCE_ROOT; }; + DC0210D3F25F470C86F914B3 /* ColladaParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaParser.h; path = code/ColladaParser.h; sourceTree = SOURCE_ROOT; }; + DC67FF8B4313494F8C03D840 /* XMLTools.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XMLTools.h; path = code/XMLTools.h; sourceTree = SOURCE_ROOT; }; + DD3D18BC2E58447D9879CB00 /* OptimizeMeshes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OptimizeMeshes.h; path = code/OptimizeMeshes.h; sourceTree = SOURCE_ROOT; }; + DD4E4641B0FE4369BF3775C3 /* MDCNormalTable.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDCNormalTable.h; path = code/MDCNormalTable.h; sourceTree = SOURCE_ROOT; }; + DD7FFD53046F4AEB898C0832 /* IRRMeshLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IRRMeshLoader.cpp; path = code/IRRMeshLoader.cpp; sourceTree = SOURCE_ROOT; }; + DDDE82BDF4F94E0EA35649A4 /* LimitBoneWeightsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LimitBoneWeightsProcess.h; path = code/LimitBoneWeightsProcess.h; sourceTree = SOURCE_ROOT; }; + DE0D259917354C80BE1CC791 /* BlenderScene.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderScene.cpp; path = code/BlenderScene.cpp; sourceTree = SOURCE_ROOT; }; + DE811A81663A492A84E13937 /* ObjExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjExporter.cpp; path = code/ObjExporter.cpp; sourceTree = SOURCE_ROOT; }; + DF76D04D95E649BCBC15E64F /* TextureTransform.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TextureTransform.cpp; path = code/TextureTransform.cpp; sourceTree = SOURCE_ROOT; }; + DFF8AF202CAA40E69D1A2BD0 /* static_assert.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = static_assert.hpp; path = code/BoostWorkaround/boost/static_assert.hpp; sourceTree = SOURCE_ROOT; }; + E01801CB159D47928B3D96B5 /* TinyFormatter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TinyFormatter.h; path = code/TinyFormatter.h; sourceTree = SOURCE_ROOT; }; + E065DB38B0284196A9283CA3 /* LimitBoneWeightsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LimitBoneWeightsProcess.cpp; path = code/LimitBoneWeightsProcess.cpp; sourceTree = SOURCE_ROOT; }; + E11A39E91576445599DF2AC4 /* STEPFileEncoding.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STEPFileEncoding.cpp; path = code/STEPFileEncoding.cpp; sourceTree = SOURCE_ROOT; }; + E1313C36045444619026E9FB /* cfileio.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cfileio.h; path = include/assimp/cfileio.h; sourceTree = SOURCE_ROOT; }; + E24E950227C848D3A759F5C2 /* MDLLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDLLoader.h; path = code/MDLLoader.h; sourceTree = SOURCE_ROOT; }; + E51043448F1744FFA78526D5 /* PlyExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PlyExporter.cpp; path = code/PlyExporter.cpp; sourceTree = SOURCE_ROOT; }; + E6332CD992D447CA910DA456 /* FBXUtil.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXUtil.cpp; path = code/FBXUtil.cpp; sourceTree = SOURCE_ROOT; }; + E663847651834244834CB9F5 /* PostStepRegistry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PostStepRegistry.cpp; path = code/PostStepRegistry.cpp; sourceTree = SOURCE_ROOT; }; + E7E85BF696E74CFAAEBF895C /* FBXTokenizer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXTokenizer.h; path = code/FBXTokenizer.h; sourceTree = SOURCE_ROOT; }; + E81BAB0ED0854DDFA62CB956 /* pushpack1.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = pushpack1.h; path = include/assimp/Compiler/pushpack1.h; sourceTree = SOURCE_ROOT; }; + E9ED3048A21E483F9C2721F4 /* mesh.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = mesh.h; path = include/assimp/mesh.h; sourceTree = SOURCE_ROOT; }; + EAD338BE19AE4C2E897B38B6 /* RawLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RawLoader.h; path = code/RawLoader.h; sourceTree = SOURCE_ROOT; }; + EAD34F1AA6664B6B935C9421 /* FBXAnimation.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXAnimation.cpp; path = code/FBXAnimation.cpp; sourceTree = SOURCE_ROOT; }; + ECCBBF2D75A44335AB93C84A /* 3DSExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = 3DSExporter.cpp; path = code/3DSExporter.cpp; sourceTree = SOURCE_ROOT; }; + ED20428B31DF46C6A9D65322 /* StreamReader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StreamReader.h; path = code/StreamReader.h; sourceTree = SOURCE_ROOT; }; + EE545B58FA1246C792C6AD01 /* shapes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = shapes.h; path = contrib/poly2tri/poly2tri/common/shapes.h; sourceTree = SOURCE_ROOT; }; + EE6163EB035149A6B8139DB8 /* FBXMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXMaterial.cpp; path = code/FBXMaterial.cpp; sourceTree = SOURCE_ROOT; }; + EF9F805A4BA4428CA98C9DE5 /* OgreXmlSerializer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreXmlSerializer.cpp; path = code/OgreXmlSerializer.cpp; sourceTree = SOURCE_ROOT; }; + EFD557FE2C3A46D78F070655 /* OFFLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OFFLoader.cpp; path = code/OFFLoader.cpp; sourceTree = SOURCE_ROOT; }; + F1076BAC69DB4935A93045A8 /* ACLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ACLoader.cpp; path = code/ACLoader.cpp; sourceTree = SOURCE_ROOT; }; + F1A7BD0B5CAE48699FCAEBD1 /* MDLDefaultColorMap.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDLDefaultColorMap.h; path = code/MDLDefaultColorMap.h; sourceTree = SOURCE_ROOT; }; + F22D5BA425444A028DA42BEA /* FBXDocument.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXDocument.cpp; path = code/FBXDocument.cpp; sourceTree = SOURCE_ROOT; }; + F44E3625C31843B0AFA1A744 /* AssxmlExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = AssxmlExporter.h; path = code/AssxmlExporter.h; sourceTree = SOURCE_ROOT; }; + F468200042534D7CA2C9D891 /* BaseProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BaseProcess.h; path = code/BaseProcess.h; sourceTree = SOURCE_ROOT; }; + F4AE5F74C20B400EA688B5ED /* VertexTriangleAdjacency.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = VertexTriangleAdjacency.h; path = code/VertexTriangleAdjacency.h; sourceTree = SOURCE_ROOT; }; + F4BA09C943DD49E184316D97 /* Win32DebugLogStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Win32DebugLogStream.h; path = code/Win32DebugLogStream.h; sourceTree = SOURCE_ROOT; }; + F5720C42345840CB9FEA5A40 /* BlenderModifier.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderModifier.h; path = code/BlenderModifier.h; sourceTree = SOURCE_ROOT; }; + F75457C6D026451B9267B65E /* OgreMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreMaterial.cpp; path = code/OgreMaterial.cpp; sourceTree = SOURCE_ROOT; }; + F81AE18E4AA94F9597FCB040 /* Importer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Importer.h; path = code/Importer.h; sourceTree = SOURCE_ROOT; }; + F898EEA0D9E64425A790587D /* Q3BSPFileImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPFileImporter.h; path = code/Q3BSPFileImporter.h; sourceTree = SOURCE_ROOT; }; + F8AC3A243B9C47D6B31348BA /* FBXParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXParser.h; path = code/FBXParser.h; sourceTree = SOURCE_ROOT; }; + F8B1133805564E18B32FFA83 /* OgreStructs.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreStructs.h; path = code/OgreStructs.h; sourceTree = SOURCE_ROOT; }; + F9FEF4D69EFC4605A4F752E5 /* DefaultIOStream.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DefaultIOStream.cpp; path = code/DefaultIOStream.cpp; sourceTree = SOURCE_ROOT; }; + FAB6BC13FCFE40F5801D0972 /* BaseProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BaseProcess.cpp; path = code/BaseProcess.cpp; sourceTree = SOURCE_ROOT; }; + FAC67CC462484F92A2CBD7D3 /* poppack1.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = poppack1.h; path = include/assimp/Compiler/poppack1.h; sourceTree = SOURCE_ROOT; }; + FB1E84BE85A34F98A44BBB2B /* vector2.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = vector2.h; path = include/assimp/vector2.h; sourceTree = SOURCE_ROOT; }; + FB2510D46F504365A03EE8A8 /* TriangulateProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TriangulateProcess.h; path = code/TriangulateProcess.h; sourceTree = SOURCE_ROOT; }; + FB4ABA17AF264257BDA4D921 /* RemoveVCProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RemoveVCProcess.cpp; path = code/RemoveVCProcess.cpp; sourceTree = SOURCE_ROOT; }; + FB55283BC24C4A1CA86C4900 /* PolyTools.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PolyTools.h; path = code/PolyTools.h; sourceTree = SOURCE_ROOT; }; + FBC2BA7F2269489694BC890D /* FBXProperties.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXProperties.h; path = code/FBXProperties.h; sourceTree = SOURCE_ROOT; }; + FC0801BA1F95494498A089AF /* version.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = version.h; path = include/assimp/version.h; sourceTree = SOURCE_ROOT; }; + FCCB4BB481FB461688FE2F29 /* B3DImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = B3DImporter.cpp; path = code/B3DImporter.cpp; sourceTree = SOURCE_ROOT; }; + FD84CFD1BD3E4AF4BA622BB8 /* MD2NormalTable.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD2NormalTable.h; path = code/MD2NormalTable.h; sourceTree = SOURCE_ROOT; }; + FD9BEC6B8A264AB092F98E20 /* SMDLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SMDLoader.cpp; path = code/SMDLoader.cpp; sourceTree = SOURCE_ROOT; }; + FEEA39CDD7934999B89E2B4D /* MaterialSystem.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MaterialSystem.h; path = code/MaterialSystem.h; sourceTree = SOURCE_ROOT; }; + FF4E90FB1A3446F095ECC8BD /* Exporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Exporter.cpp; path = code/Exporter.cpp; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7F79227D1AB43AC3005A8E5D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0117589D2B25420F831BA4CE /* MS3D */ = { + isa = PBXGroup; + children = ( + A7A990C6FF244DC397B7BA7C /* MS3DLoader.cpp */, + 6347FA5D391D4320B9457D3F /* MS3DLoader.h */, + ); + name = MS3D; + sourceTree = ""; + }; + 0593669570C8417B8FE0C89E /* Obj */ = { + isa = PBXGroup; + children = ( + DE811A81663A492A84E13937 /* ObjExporter.cpp */, + 91EF6411C40946758A06144F /* ObjExporter.h */, + 005DFE3B6FFC4BEBB7055330 /* ObjFileData.h */, + 862131D4574B4CABA5EC957B /* ObjFileImporter.cpp */, + 1FC965B1F11B45F98051C565 /* ObjFileImporter.h */, + 4108529663904025B21E526B /* ObjFileMtlImporter.cpp */, + 180177D50FDA4C10AD629DC2 /* ObjFileMtlImporter.h */, + ACF73EEAB2424213BF7158D5 /* ObjFileParser.cpp */, + 333F4676A92043739F5A9D32 /* ObjFileParser.h */, + 8FE8B4781BB3406EB3452154 /* ObjTools.h */, + ); + name = Obj; + sourceTree = ""; + }; + 09D1759329AB410E92DC273A /* Collada */ = { + isa = PBXGroup; + children = ( + 1C0527629078403F81CFD117 /* ColladaExporter.cpp */, + 638B3F6AC17A435C9B86C86C /* ColladaExporter.h */, + 7C10178C0B7241DD874A0AF3 /* ColladaHelper.h */, + 1A4706D216414D4F8AA72EC9 /* ColladaLoader.cpp */, + 6981B16018CF46CAA54C0BAA /* ColladaLoader.h */, + 420D77ED33554D54AA4D50EF /* ColladaParser.cpp */, + DC0210D3F25F470C86F914B3 /* ColladaParser.h */, + ); + name = Collada; + sourceTree = ""; + }; + 0C22F81E750C429183194A1D /* Assxml */ = { + isa = PBXGroup; + children = ( + B3E8A1BEF8E74F04AE06871B /* AssxmlExporter.cpp */, + F44E3625C31843B0AFA1A744 /* AssxmlExporter.h */, + ); + name = Assxml; + sourceTree = ""; + }; + 1126F68352DC4FD49AC55DD7 /* ConvertUTF */ = { + isa = PBXGroup; + children = ( + 9A0960F123634603B15EEA38 /* ConvertUTF.c */, + 6F88E78E61FC4A01BC30BE85 /* ConvertUTF.h */, + ); + name = ConvertUTF; + sourceTree = ""; + }; + 16ED8F46E8ED44BAB8D7BA1B /* MaterialSystem */ = { + isa = PBXGroup; + children = ( + 7FF72CB6E99E40E19AE0E64C /* MaterialSystem.cpp */, + FEEA39CDD7934999B89E2B4D /* MaterialSystem.h */, + ); + name = MaterialSystem; + sourceTree = ""; + }; + 1AC84A1DBE804A71B13E06C2 /* Clipper */ = { + isa = PBXGroup; + children = ( + 59F8A11A7AED45CC94CEDF28 /* clipper.cpp */, + C490BBF1881240EEA4A96315 /* clipper.hpp */, + ); + name = Clipper; + sourceTree = ""; + }; + 1BF60AA5F4B147508EB44D8C /* Exporter */ = { + isa = PBXGroup; + children = ( + A1A9535EDF9A4FF2B8DABD7D /* AssimpCExport.cpp */, + 23097CBD64E343738B8F22EE /* BlobIOSystem.h */, + FF4E90FB1A3446F095ECC8BD /* Exporter.cpp */, + ); + name = Exporter; + sourceTree = ""; + }; + 2B78DE034A954FAD96DA8432 /* IFC */ = { + isa = PBXGroup; + children = ( + 285D1FDA48EC4DD8933B603E /* IFCBoolean.cpp */, + 2E7FD92FFCF441B0A60FC8B4 /* IFCCurve.cpp */, + 3267EBBA6EEB435F83FF25E4 /* IFCGeometry.cpp */, + D0E9BB0220704C5D93CE7CE9 /* IFCLoader.cpp */, + 2BE34AF1CE0C4767ACE21597 /* IFCLoader.h */, + 0014AE5E87A74AAA9EF0EC4B /* IFCMaterial.cpp */, + 74679D2078FD46ED9AC73355 /* IFCOpenings.cpp */, + 46E9F455A3284DB399986293 /* IFCProfile.cpp */, + 3F5D1E6368384D429BA29D5A /* IFCReaderGen.cpp */, + 6162B57DE81A4E538430056E /* IFCReaderGen.h */, + 59E3D32E3FC7438DB148537F /* IFCUtil.cpp */, + 13BFADA520C04B15AE256CC2 /* IFCUtil.h */, + 47FF3063906E4786ABF0939B /* STEPFile.h */, + E11A39E91576445599DF2AC4 /* STEPFileEncoding.cpp */, + D56A4C70F65D4E07BD792D2C /* STEPFileEncoding.h */, + CDE3ECA98173418A9F997992 /* STEPFileReader.cpp */, + A3D3024C3A59423487A125C8 /* STEPFileReader.h */, + ); + name = IFC; + sourceTree = ""; + }; + 2CA4999D40FC406B97E1FFD3 /* Compiler */ = { + isa = PBXGroup; + children = ( + FAC67CC462484F92A2CBD7D3 /* poppack1.h */, + 278FB5C8BD814F2DAE04A1C7 /* pstdint.h */, + E81BAB0ED0854DDFA62CB956 /* pushpack1.h */, + ); + name = Compiler; + sourceTree = ""; + }; + 2DC7AE369B84444B9649035D /* assimp */ = { + isa = PBXGroup; + children = ( + DB181885BFCC44F594A1FA01 /* Source Files */, + 628C9A9A9FA640B9AA1DAC09 /* Common */, + 874C614E5BEB41419F0EEE1C /* Logging */, + 1BF60AA5F4B147508EB44D8C /* Exporter */, + D3013C8FC8034BC6859BC020 /* PostProcessing */, + 9AC9FD0CD777436C9C7291FF /* 3DS */, + 98D9A21F310D47DD8F390780 /* AC */, + CB3420FADCED418CACDBB584 /* ASE */, + A7F45F8E82C445EBA7D67C36 /* Assbin */, + 0C22F81E750C429183194A1D /* Assxml */, + A1E04517F0D440CDB46985A7 /* B3D */, + 91C8DA33C37E491BBAD264C5 /* BVH */, + 09D1759329AB410E92DC273A /* Collada */, + 5F3147F7FF1044D49A824DBC /* DXF */, + DD5B35196B184EFB820D1FBB /* CSM */, + 723B9CB1C871444FBB302576 /* HMP */, + 6CB3C1AECE8A4745861D913D /* Irr */, + 873AA0EB80814B0A9461BB7E /* LWO */, + 32F48CB0DF784B6BA63A5025 /* LWS */, + F9261D592F00437EAFC663B5 /* MD2 */, + 7D3FF9CAC50E41F0B59B9758 /* MD3 */, + 97326C49E0E34D43AE80F0FF /* MD5 */, + CB981D90CEF4472191978170 /* MDC */, + EF7D37EB84AF45FC8BF47E7F /* MDL */, + 16ED8F46E8ED44BAB8D7BA1B /* MaterialSystem */, + CF7D1A0DBB134AC4BCFE3C3F /* NFF */, + 8438F0F891674542AF8F2302 /* OFFFormat */, + 0593669570C8417B8FE0C89E /* Obj */, + 6D12DDA749D645C68DBED62E /* Ogre */, + 7FBE9FE41B65ABEF00D2115E /* OpenGEX */, + 462ED039D874460E97B08346 /* Ply */, + F0273EDFDBD34EDAA6678613 /* Q3D */, + C3D412701D614559B698CED1 /* Q3BSP */, + 9A8E68D1ECFC49B9BB435F1C /* Raw */, + 8C2B1B7516DD4C4798F5048F /* SMD */, + 2E29D94CA6DA405EB4AF90E0 /* STL */, + 3A5EB041B5CD4F98802B2540 /* Terragen */, + 8565C30231D64E81BB2B4ECD /* Unreal */, + 96A36CD42ADB4BBBB54004E1 /* XFile */, + 6E21649785DD4DB08D9A505D /* Extra */, + 0117589D2B25420F831BA4CE /* MS3D */, + DAFF6641A88441AFBE8B99B1 /* COB */, + 71D6A260C79746D3B50849D2 /* BLENDER */, + 71199EE27B264D74B9D0A1C2 /* NDO */, + 2B78DE034A954FAD96DA8432 /* IFC */, + 2FC31A6272B94FB681FB8087 /* XGL */, + 7F21D60E8DCD4C65923BD76C /* FBX */, + 6B385D1E46704FB7BABB2D90 /* IrrXML */, + 1126F68352DC4FD49AC55DD7 /* ConvertUTF */, + 8B032622745B45FDB154A53C /* unzip */, + F61A479614764D11AC3311A8 /* Poly2Tri */, + 1AC84A1DBE804A71B13E06C2 /* Clipper */, + 3B11CB13DD484F938D3E3792 /* Boost */, + FCFE51BCE7384933A972EDEE /* Header Files */, + 2CA4999D40FC406B97E1FFD3 /* Compiler */, + ); + name = assimp; + sourceTree = ""; + }; + 2E29D94CA6DA405EB4AF90E0 /* STL */ = { + isa = PBXGroup; + children = ( + 89D2D359BD854D8AA60CB720 /* STLExporter.cpp */, + 88ADA502481B403191BD35F0 /* STLExporter.h */, + 4D2F1605B9484B08BB33402D /* STLLoader.cpp */, + C6D3C3E2BA2F49F2B17E7580 /* STLLoader.h */, + ); + name = STL; + sourceTree = ""; + }; + 2FC31A6272B94FB681FB8087 /* XGL */ = { + isa = PBXGroup; + children = ( + 8E395349546A4FDF843E6963 /* XGLLoader.cpp */, + 501B18C2B590455D8A3C3E78 /* XGLLoader.h */, + ); + name = XGL; + sourceTree = ""; + }; + 32F48CB0DF784B6BA63A5025 /* LWS */ = { + isa = PBXGroup; + children = ( + AFF41974881F466A9561BE4B /* LWSLoader.cpp */, + 68703F99581F49CB9E2B9F37 /* LWSLoader.h */, + ); + name = LWS; + sourceTree = ""; + }; + 3A5EB041B5CD4F98802B2540 /* Terragen */ = { + isa = PBXGroup; + children = ( + 4866DA5A7BFD49F79B61CBF8 /* TerragenLoader.cpp */, + 815702BED5644DD5B242F347 /* TerragenLoader.h */, + ); + name = Terragen; + sourceTree = ""; + }; + 3B11CB13DD484F938D3E3792 /* Boost */ = { + isa = PBXGroup; + children = ( + AAD3EA9B0BB84A788FCCA83E /* foreach.hpp */, + 1DC56C794E434BA28E5CCC36 /* format.hpp */, + 96A02CBA1AE642BD9519719D /* make_shared.hpp */, + 967D69AC1A344D4E988F0B2C /* common_factor_rt.hpp */, + C2C9EAC9B5B74AC397B070E8 /* scoped_array.hpp */, + 7644CE6B26D740258577EE9D /* scoped_ptr.hpp */, + 8C9AEFFFF3B948148D32D76F /* shared_array.hpp */, + 3E84DEFC1E0646AD82F79998 /* shared_ptr.hpp */, + DFF8AF202CAA40E69D1A2BD0 /* static_assert.hpp */, + A7CEBC6894424B888326CAB2 /* tuple.hpp */, + ); + name = Boost; + sourceTree = ""; + }; + 462ED039D874460E97B08346 /* Ply */ = { + isa = PBXGroup; + children = ( + E51043448F1744FFA78526D5 /* PlyExporter.cpp */, + CC5D5CA1789448E9869B9669 /* PlyExporter.h */, + 409C98EE093C499B8A574CA9 /* PlyLoader.cpp */, + 91D49B3C51684882A01EA492 /* PlyLoader.h */, + 2C4D504725E540109530E254 /* PlyParser.cpp */, + 45F6A2B351AB4B749E55B299 /* PlyParser.h */, + ); + name = Ply; + sourceTree = ""; + }; + 5F3147F7FF1044D49A824DBC /* DXF */ = { + isa = PBXGroup; + children = ( + B6982D8069A145E5B9F97684 /* DXFHelper.h */, + 466D6B9A7CCD402D9AA87071 /* DXFLoader.cpp */, + 7BDF90B124F74A39A5EB3B02 /* DXFLoader.h */, + ); + name = DXF; + sourceTree = ""; + }; + 628C9A9A9FA640B9AA1DAC09 /* Common */ = { + isa = PBXGroup; + children = ( + A58410FEAA884A2D8D73ACCE /* BaseImporter.cpp */, + 32170F499DAC4E4595AF6D6B /* BaseImporter.h */, + FAB6BC13FCFE40F5801D0972 /* BaseProcess.cpp */, + F468200042534D7CA2C9D891 /* BaseProcess.h */, + 10238FBD7A9D401A82D667CB /* Bitmap.cpp */, + 49AFF879142C4BA4865843DC /* Bitmap.h */, + 339E56B5FD264481BBF21835 /* CInterfaceIOWrapper.h */, + F9FEF4D69EFC4605A4F752E5 /* DefaultIOStream.cpp */, + 32CC68350B7640ACA7C83DDA /* DefaultIOStream.h */, + 1D502654EF864101A2DA9476 /* DefaultIOSystem.cpp */, + D9AB66BD27E246A18091626F /* DefaultIOSystem.h */, + B7192C50B16142398B7CD221 /* DefaultProgressHandler.h */, + 3ACFF3FC39C74C4A966C0FEA /* GenericProperty.h */, + 9C5E3F9248B64C7EBF20EC27 /* Hash.h */, + 6AC645CEB6F74AE5A62DF68B /* IFF.h */, + 9472EFB6831740DD91471337 /* Importer.cpp */, + F81AE18E4AA94F9597FCB040 /* Importer.h */, + D029CE902F8045B0B3AFFDDB /* ImporterRegistry.cpp */, + 680FBD79376A41B690C405B8 /* LineSplitter.h */, + D82B5BA87B184532BE74D24F /* LogAux.h */, + 7DC4B0B5E57F4F4892CC823E /* MemoryIOWrapper.h */, + 0C1B00249A554394A4F9CF2A /* ParsingUtils.h */, + E663847651834244834CB9F5 /* PostStepRegistry.cpp */, + 5C1EA03E3AE24AA5A778B7F1 /* Profiler.h */, + 6A86069DEEDC42B88634F78D /* RemoveComments.cpp */, + B4086213AE40445F817FA840 /* RemoveComments.h */, + 52836A0629E24447B924750A /* SGSpatialSort.cpp */, + 8299401C3E4A43A18E887DC1 /* SGSpatialSort.h */, + 73A3D87FF2C04C3BA3684F54 /* SceneCombiner.cpp */, + 8476FEE874C1404B9B4B9617 /* SceneCombiner.h */, + 1775DE08FC8647EB896A0FB3 /* ScenePreprocessor.cpp */, + 4FE1E4726B144AD1B922A1A0 /* ScenePreprocessor.h */, + 97914BDA4AA34081855BF16C /* ScenePrivate.h */, + 9B2827B3E64147E08A5AD334 /* SkeletonMeshBuilder.cpp */, + 45BC2EB74251493CBBFAEB5D /* SkeletonMeshBuilder.h */, + 2DCF6F156A3A4B4C807E5368 /* SmoothingGroups.h */, + 8EEC6646FC044D1E9658A590 /* SpatialSort.cpp */, + 957FBC18FED2484F83308E36 /* SpatialSort.h */, + 99A4349D505F4CC593F48CF6 /* SplitByBoneCountProcess.cpp */, + B211101B342C414A9E43B7BC /* SplitByBoneCountProcess.h */, + C18C5023460E4D17B8C922D7 /* StandardShapes.cpp */, + 296407DE471C4F298742FB59 /* StandardShapes.h */, + ED20428B31DF46C6A9D65322 /* StreamReader.h */, + 7E8BA0D338C9433587BC6C35 /* StreamWriter.h */, + BDD30C77BB68497EA3B7F2F7 /* StringComparison.h */, + 4BBDEB63CFEB4F2EAA95358D /* Subdivision.cpp */, + A72115ED828F4069A427B460 /* Subdivision.h */, + 6F65B6129F774AEDB8DC845A /* TargetAnimation.cpp */, + A7733823362B4A389102D177 /* TargetAnimation.h */, + E01801CB159D47928B3D96B5 /* TinyFormatter.h */, + 1533BE4C09F1430C8BF4D248 /* Vertex.h */, + 0AAF26EBF0A64ABDB840BA64 /* VertexTriangleAdjacency.cpp */, + F4AE5F74C20B400EA688B5ED /* VertexTriangleAdjacency.h */, + DC67FF8B4313494F8C03D840 /* XMLTools.h */, + 1AF1EE8EFE594A40ACE03D19 /* fast_atof.h */, + 262DFE65C6D34442AA79D15A /* qnan.h */, + ); + name = Common; + sourceTree = ""; + }; + 6B385D1E46704FB7BABB2D90 /* IrrXML */ = { + isa = PBXGroup; + children = ( + D1073FF20359469D921C9316 /* irrXMLWrapper.h */, + D40F70AC841D4B788B5C696B /* CXMLReaderImpl.h */, + 02587469A85540EE875B04B5 /* heapsort.h */, + 49FE5C30FC854A3EBD0E9C19 /* irrArray.h */, + 5D4E64EABD9548A59E9637AF /* irrString.h */, + 4936396409984881858E7B15 /* irrTypes.h */, + 64C6BACDA5DD4139AA26EE81 /* irrXML.cpp */, + 12E167EBA81B4CD3A241D7AF /* irrXML.h */, + ); + name = IrrXML; + sourceTree = ""; + }; + 6CB3C1AECE8A4745861D913D /* Irr */ = { + isa = PBXGroup; + children = ( + 97DFA90F9D0C4B999C150B10 /* IRRLoader.cpp */, + 1011FC45108745A7BBA98904 /* IRRLoader.h */, + DD7FFD53046F4AEB898C0832 /* IRRMeshLoader.cpp */, + 670FE6DD7EDF421488F2F97F /* IRRMeshLoader.h */, + CC54A231FF6B4B0CABCFD167 /* IRRShared.cpp */, + B04FE3598E344EC09B59CA2F /* IRRShared.h */, + ); + name = Irr; + sourceTree = ""; + }; + 6D12DDA749D645C68DBED62E /* Ogre */ = { + isa = PBXGroup; + children = ( + 56ADEC4899C047F2839AD791 /* OgreBinarySerializer.cpp */, + 916456789C75419DB1436FAD /* OgreBinarySerializer.h */, + 923283A9791E4B4E86D623FC /* OgreImporter.cpp */, + 71F65BF6936E4E97A5933EF9 /* OgreImporter.h */, + F75457C6D026451B9267B65E /* OgreMaterial.cpp */, + 6F49958B5CCF423681133515 /* OgreParsingUtils.h */, + 79A49EFE23E34E1CBA2E4377 /* OgreStructs.cpp */, + F8B1133805564E18B32FFA83 /* OgreStructs.h */, + EF9F805A4BA4428CA98C9DE5 /* OgreXmlSerializer.cpp */, + AC699876B6364EC1878CBA44 /* OgreXmlSerializer.h */, + ); + name = Ogre; + sourceTree = ""; + }; + 6E21649785DD4DB08D9A505D /* Extra */ = { + isa = PBXGroup; + children = ( + 00EB692107B84590B0560BFB /* MD4FileData.h */, + ); + name = Extra; + sourceTree = ""; + }; + 71199EE27B264D74B9D0A1C2 /* NDO */ = { + isa = PBXGroup; + children = ( + B4F1B5789CA540C78FB9219D /* NDOLoader.cpp */, + 37A3E0E2BB484DD8B9FCCA5E /* NDOLoader.h */, + ); + name = NDO; + sourceTree = ""; + }; + 71D6A260C79746D3B50849D2 /* BLENDER */ = { + isa = PBXGroup; + children = ( + 603AFA882AFF49AEAC2C8FA2 /* BlenderBMesh.cpp */, + 4568875B66584E12AA1538C7 /* BlenderBMesh.h */, + B65258E349704523BC43904D /* BlenderDNA.cpp */, + 72832410F47C44E3BAE709C2 /* BlenderDNA.h */, + 43899EB0B0704A9DB8F0C54F /* BlenderDNA.inl */, + 7CAF8A3096E04CB983B53CC1 /* BlenderIntermediate.h */, + 906F71D342544BF381E1318E /* BlenderLoader.cpp */, + 157C3CC81232428FA535E05F /* BlenderLoader.h */, + 3106D75C13874F5AB3EBBFE7 /* BlenderModifier.cpp */, + F5720C42345840CB9FEA5A40 /* BlenderModifier.h */, + DE0D259917354C80BE1CC791 /* BlenderScene.cpp */, + B522B83A39CA461CBCABE25A /* BlenderScene.h */, + 76D801D898C4443D8240EDB7 /* BlenderSceneGen.h */, + 12C5DD7A285042EDB1897FAE /* BlenderTessellator.cpp */, + 59A1859480754E90B958CA85 /* BlenderTessellator.h */, + ); + name = BLENDER; + sourceTree = ""; + }; + 723B9CB1C871444FBB302576 /* HMP */ = { + isa = PBXGroup; + children = ( + 71EAFDE1910B4A54AAAF2101 /* HMPFileData.h */, + 43ABFF591F374920A5E18A24 /* HMPLoader.cpp */, + 5631CE86F56F458EA0E2415F /* HMPLoader.h */, + 7C63156710964DEDAC0929BD /* HalfLifeFileData.h */, + ); + name = HMP; + sourceTree = ""; + }; + 7D3FF9CAC50E41F0B59B9758 /* MD3 */ = { + isa = PBXGroup; + children = ( + 08E8379F20984AD59515AD95 /* MD3FileData.h */, + 563FBACCFD774BDEA4AEAC10 /* MD3Loader.cpp */, + 1CBCEE37D89145F19F23F036 /* MD3Loader.h */, + ); + name = MD3; + sourceTree = ""; + }; + 7F21D60E8DCD4C65923BD76C /* FBX */ = { + isa = PBXGroup; + children = ( + EAD34F1AA6664B6B935C9421 /* FBXAnimation.cpp */, + 1108AC28566B4D2B9F27C691 /* FBXBinaryTokenizer.cpp */, + 26BF681530B04B73961997CB /* FBXCompileConfig.h */, + A7A56A688A3845768410F500 /* FBXConverter.cpp */, + A7A86F81858F4D928A568E17 /* FBXConverter.h */, + 9855496CEA774F4FA7FBB862 /* FBXDeformer.cpp */, + F22D5BA425444A028DA42BEA /* FBXDocument.cpp */, + 0EF256EC06E345EB930772EC /* FBXDocument.h */, + BB38E7E7661842448F008372 /* FBXDocumentUtil.cpp */, + C17C5037C995420C8D259C0C /* FBXImportSettings.h */, + B4C688FA08F44716855CDD3C /* FBXImporter.cpp */, + AA4946AEDB9F4F22873C4C4F /* FBXImporter.h */, + EE6163EB035149A6B8139DB8 /* FBXMaterial.cpp */, + 42E110B9E6924AF9B55AE65A /* FBXMeshGeometry.cpp */, + 1A61BDC559CE4186B03C0396 /* FBXModel.cpp */, + 33B70115CA54405F895BA471 /* FBXNodeAttribute.cpp */, + 5F373DF3B03B4B848B78EAD2 /* FBXParser.cpp */, + F8AC3A243B9C47D6B31348BA /* FBXParser.h */, + 9D203F78B24C4D7E8E2084A3 /* FBXProperties.cpp */, + FBC2BA7F2269489694BC890D /* FBXProperties.h */, + CF07D05DC86F4C98BC42FDCF /* FBXTokenizer.cpp */, + E7E85BF696E74CFAAEBF895C /* FBXTokenizer.h */, + E6332CD992D447CA910DA456 /* FBXUtil.cpp */, + 89473420F7E448A7BE71FCBA /* FBXUtil.h */, + ); + name = FBX; + sourceTree = ""; + }; + 7F392D931AB2C7C200D952EB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7F29EF981AB26C4900E9D380 /* libz.1.dylib */, + 7F392D921AB2C7BB00D952EB /* libc++.dylib */, + ); + name = Frameworks; + sourceTree = ""; + }; + 7FBE9FE41B65ABEF00D2115E /* OpenGEX */ = { + isa = PBXGroup; + children = ( + 7FBE9FE51B65AC1200D2115E /* OpenGEXExporter.cpp */, + 7FBE9FE61B65AC1200D2115E /* OpenGEXExporter.h */, + 7FBE9FE71B65AC1200D2115E /* OpenGEXImporter.cpp */, + 7FBE9FE81B65AC1200D2115E /* OpenGEXImporter.h */, + 7FBE9FE91B65AC1200D2115E /* OpenGEXStructs.h */, + 7FBEA0051B65AF8900D2115E /* openddlparser */, + ); + name = OpenGEX; + sourceTree = ""; + }; + 7FBEA0051B65AF8900D2115E /* openddlparser */ = { + isa = PBXGroup; + children = ( + 7FBEA0081B65AF9200D2115E /* OpenDDLCommon.h */, + 7FBEA00B1B65AF9200D2115E /* OpenDDLParserUtils.h */, + 7FBEA0071B65AF9200D2115E /* DDLNode.h */, + 7F7A93A51B65D0110094C4DA /* DDLNode.cpp */, + 7FBEA00A1B65AF9200D2115E /* OpenDDLParser.h */, + 7F7A93A61B65D0110094C4DA /* OpenDDLParser.cpp */, + 7FBEA00D1B65AF9200D2115E /* Value.h */, + 7F7A93A71B65D0110094C4DA /* Value.cpp */, + ); + name = openddlparser; + sourceTree = ""; + }; + 8438F0F891674542AF8F2302 /* OFFFormat */ = { + isa = PBXGroup; + children = ( + EFD557FE2C3A46D78F070655 /* OFFLoader.cpp */, + BF94F50C216B45388CDEC1EF /* OFFLoader.h */, + ); + name = OFFFormat; + sourceTree = ""; + }; + 8565C30231D64E81BB2B4ECD /* Unreal */ = { + isa = PBXGroup; + children = ( + 3B8FD96D46314ACD8F157AC3 /* UnrealLoader.cpp */, + 27F2019E621B4CDA94DD5270 /* UnrealLoader.h */, + ); + name = Unreal; + sourceTree = ""; + }; + 873AA0EB80814B0A9461BB7E /* LWO */ = { + isa = PBXGroup; + children = ( + 680C392FFE0B4CC5ABC7CA64 /* LWOAnimation.cpp */, + A14347E954E8413CAF1455EA /* LWOAnimation.h */, + D629F6BF53864979B7619067 /* LWOBLoader.cpp */, + AFA8B6DE5B3A4E52A85041C9 /* LWOFileData.h */, + 5A4E05386C094B809A315A07 /* LWOLoader.cpp */, + 72F2DF0B93CF4D3ABAD7513D /* LWOLoader.h */, + 1ED21FC57A384CE6B4F53C0C /* LWOMaterial.cpp */, + ); + name = LWO; + sourceTree = ""; + }; + 874C614E5BEB41419F0EEE1C /* Logging */ = { + isa = PBXGroup; + children = ( + A9E9EB834E09420197C3FB8C /* DefaultLogger.cpp */, + 1520A11AA6E54812939B1FBB /* FileLogStream.h */, + 4CBC1122A79D4F6C94E36CE3 /* StdOStreamLogStream.h */, + F4BA09C943DD49E184316D97 /* Win32DebugLogStream.h */, + D958B0B445E64F4BA9145D82 /* DefaultLogger.hpp */, + 657B9A15EE7A4B7BA519A969 /* LogStream.hpp */, + 56CE07D64D114C4BAB6D9F08 /* Logger.hpp */, + 8D977E197CA4477AB9F3278C /* NullLogger.hpp */, + ); + name = Logging; + sourceTree = ""; + }; + 8B032622745B45FDB154A53C /* unzip */ = { + isa = PBXGroup; + children = ( + A4CBF9157F01460ABEDEBF28 /* crypt.h */, + AF75E6049338489BB256D295 /* ioapi.c */, + 72F637AC7D9E4FBFBB9201CE /* ioapi.h */, + 973D4231A4AA4925B019FEEE /* unzip.c */, + 9293C5A353F9497A850E05D5 /* unzip.h */, + ); + name = unzip; + sourceTree = ""; + }; + 8C2B1B7516DD4C4798F5048F /* SMD */ = { + isa = PBXGroup; + children = ( + FD9BEC6B8A264AB092F98E20 /* SMDLoader.cpp */, + C582480917FF4EB09C164D70 /* SMDLoader.h */, + ); + name = SMD; + sourceTree = ""; + }; + 91C8DA33C37E491BBAD264C5 /* BVH */ = { + isa = PBXGroup; + children = ( + C80B9A3AF4204AE08AA50BAE /* BVHLoader.cpp */, + 45E342A1499E4F03ADD49028 /* BVHLoader.h */, + ); + name = BVH; + sourceTree = ""; + }; + 96A36CD42ADB4BBBB54004E1 /* XFile */ = { + isa = PBXGroup; + children = ( + 435DC362E63D4CCBA68656D3 /* XFileExporter.cpp */, + A257229A058041389981CFC1 /* XFileExporter.h */, + 8F4261792A60481DA04E6E1A /* XFileHelper.h */, + 06DB494DCE4D47FDA00E8B35 /* XFileImporter.cpp */, + 53537D08E9B44A25B43B697B /* XFileImporter.h */, + 74C02A113B804568A7E39CBC /* XFileParser.cpp */, + 3551D90CCED1454A8B912066 /* XFileParser.h */, + ); + name = XFile; + sourceTree = ""; + }; + 97326C49E0E34D43AE80F0FF /* MD5 */ = { + isa = PBXGroup; + children = ( + A277DBC1EFB944F995659A20 /* MD5Loader.cpp */, + 6BAB32C8E06E43689FC5E7EA /* MD5Loader.h */, + 0BC5FD00572F4C58B267A0EC /* MD5Parser.cpp */, + 43FC808D2F4745ACB06A9D33 /* MD5Parser.h */, + ); + name = MD5; + sourceTree = ""; + }; + 98D9A21F310D47DD8F390780 /* AC */ = { + isa = PBXGroup; + children = ( + F1076BAC69DB4935A93045A8 /* ACLoader.cpp */, + 4DABF3CB245F4246B0184513 /* ACLoader.h */, + ); + name = AC; + sourceTree = ""; + }; + 9A8E68D1ECFC49B9BB435F1C /* Raw */ = { + isa = PBXGroup; + children = ( + 1D4A669762194B9D9A26DD20 /* RawLoader.cpp */, + EAD338BE19AE4C2E897B38B6 /* RawLoader.h */, + ); + name = Raw; + sourceTree = ""; + }; + 9AC9FD0CD777436C9C7291FF /* 3DS */ = { + isa = PBXGroup; + children = ( + 15221A74FC9C4B2AAA7306E3 /* 3DSConverter.cpp */, + ECCBBF2D75A44335AB93C84A /* 3DSExporter.cpp */, + 0B519CCAB4B241E59C567077 /* 3DSExporter.h */, + CB042D863BD447FFB117AE34 /* 3DSHelper.h */, + 02E9476D129940BF84DE6682 /* 3DSLoader.cpp */, + A06CBE89CFAB48E786F7A5C0 /* 3DSLoader.h */, + ); + name = 3DS; + sourceTree = ""; + }; + A1E04517F0D440CDB46985A7 /* B3D */ = { + isa = PBXGroup; + children = ( + FCCB4BB481FB461688FE2F29 /* B3DImporter.cpp */, + 42E68041B1C442E3B49FC304 /* B3DImporter.h */, + ); + name = B3D; + sourceTree = ""; + }; + A7F45F8E82C445EBA7D67C36 /* Assbin */ = { + isa = PBXGroup; + children = ( + 6389F68312384CFD847B1D13 /* AssbinExporter.cpp */, + 6CC21F1D0E4140FE923E4EE6 /* AssbinExporter.h */, + D9FEEF58B24548F782A5D53C /* AssbinLoader.cpp */, + 0CCD090F58EB40ACBBDBBDEE /* AssbinLoader.h */, + ); + name = Assbin; + sourceTree = ""; + }; + AF05BC16567A496BB5DCB2F0 /* Products */ = { + isa = PBXGroup; + children = ( + 7F7922801AB43AC3005A8E5D /* libassimp.a */, + ); + name = Products; + sourceTree = ""; + }; + BCC52F1D5AF74E54A2D69524 = { + isa = PBXGroup; + children = ( + 2DC7AE369B84444B9649035D /* assimp */, + 7F392D931AB2C7C200D952EB /* Frameworks */, + AF05BC16567A496BB5DCB2F0 /* Products */, + ); + sourceTree = ""; + }; + C3D412701D614559B698CED1 /* Q3BSP */ = { + isa = PBXGroup; + children = ( + 6E82409E9D274D278971F3B0 /* Q3BSPFileData.h */, + A88D56FBEA084A3EA9A0ECB3 /* Q3BSPFileImporter.cpp */, + F898EEA0D9E64425A790587D /* Q3BSPFileImporter.h */, + 4A60A00727F04E049CF3AE33 /* Q3BSPFileParser.cpp */, + 5C15EEB253204E8A8E0D0E38 /* Q3BSPFileParser.h */, + 43C75175738C4119871E8BB0 /* Q3BSPZipArchive.cpp */, + 6454A961FAF44B3E9086D2F8 /* Q3BSPZipArchive.h */, + ); + name = Q3BSP; + sourceTree = ""; + }; + CB3420FADCED418CACDBB584 /* ASE */ = { + isa = PBXGroup; + children = ( + 7C477FA4D89548F1BCEDC5A0 /* ASELoader.cpp */, + 9A61AF384D4D45778698DD7D /* ASELoader.h */, + 929F59CCA32549EC884A5033 /* ASEParser.cpp */, + 27605E75944D41B0B98260A3 /* ASEParser.h */, + ); + name = ASE; + sourceTree = ""; + }; + CB981D90CEF4472191978170 /* MDC */ = { + isa = PBXGroup; + children = ( + 95641498F25A4F6FABBC03A4 /* MDCFileData.h */, + 35E4944C052A4C91BF31DE5F /* MDCLoader.cpp */, + 621E96E95F60421EB6B4525C /* MDCLoader.h */, + DD4E4641B0FE4369BF3775C3 /* MDCNormalTable.h */, + ); + name = MDC; + sourceTree = ""; + }; + CF7D1A0DBB134AC4BCFE3C3F /* NFF */ = { + isa = PBXGroup; + children = ( + 0D6E8E292F594A2DAFF53564 /* NFFLoader.cpp */, + D2869C6AD4814588A45E8F81 /* NFFLoader.h */, + ); + name = NFF; + sourceTree = ""; + }; + D3013C8FC8034BC6859BC020 /* PostProcessing */ = { + isa = PBXGroup; + children = ( + 90DD6CA40A5E41458E11FF3E /* CalcTangentsProcess.cpp */, + BBEE1CF81183473C8492FC03 /* CalcTangentsProcess.h */, + 2ABBB4561E72413EB40702C3 /* ComputeUVMappingProcess.cpp */, + B40FE1BF9D8E411493BBDE0C /* ComputeUVMappingProcess.h */, + 92D8734FFF9742B39A371B70 /* ConvertToLHProcess.cpp */, + 35A9B50143214C63A956FA27 /* ConvertToLHProcess.h */, + 6E20FCC571F144DDBD831CCB /* DeboneProcess.cpp */, + 4770D6DCA1854B4F9B85546A /* DeboneProcess.h */, + BABB7734139C452A9DDEE797 /* FindDegenerates.cpp */, + 4B571231CE2B464BBF1E853F /* FindDegenerates.h */, + C9A101D1311C4E77AAEDD94C /* FindInstancesProcess.cpp */, + 28A938B21261484998F68F4A /* FindInstancesProcess.h */, + 9B4221AA0AD2418FAA45EB64 /* FindInvalidDataProcess.cpp */, + 91FF8B1DCC0644008AE34A04 /* FindInvalidDataProcess.h */, + C54518F708BA4A328D5D7325 /* FixNormalsStep.cpp */, + 8343910BBD464297932B3CE0 /* FixNormalsStep.h */, + 982AE676D2364350B1FBD095 /* GenFaceNormalsProcess.cpp */, + 0FBF026F27F340AD9FABAF02 /* GenFaceNormalsProcess.h */, + A0AED12A1A6D4635A8CFB65A /* GenVertexNormalsProcess.cpp */, + 2AC344FBB0C34D49800F4B8A /* GenVertexNormalsProcess.h */, + 70D5FDFA995E45E6A3E8FD37 /* ImproveCacheLocality.cpp */, + 5FBE72DCC6AC485ABCF89B8C /* ImproveCacheLocality.h */, + B36DA471B9E142FC9425EC45 /* JoinVerticesProcess.cpp */, + 0A941971CBF04E8D900E9799 /* JoinVerticesProcess.h */, + E065DB38B0284196A9283CA3 /* LimitBoneWeightsProcess.cpp */, + DDDE82BDF4F94E0EA35649A4 /* LimitBoneWeightsProcess.h */, + 21B797DAB0E0427C9339AE0F /* MakeVerboseFormat.cpp */, + 0AA53AD6095A4D1088431EED /* MakeVerboseFormat.h */, + AAB9AE5328F843F5A8A3E85C /* OptimizeGraph.cpp */, + 926E8B7924144B349A88023D /* OptimizeGraph.h */, + 2ACC87E846AE4E4A86E1AEF4 /* OptimizeMeshes.cpp */, + DD3D18BC2E58447D9879CB00 /* OptimizeMeshes.h */, + FB55283BC24C4A1CA86C4900 /* PolyTools.h */, + 023C115651B54570AA2040DB /* PretransformVertices.cpp */, + 101172E4EF2E43D988B6B571 /* PretransformVertices.h */, + 890E32C714444692AA016AE5 /* ProcessHelper.cpp */, + A436C47FBF904FECB4A58462 /* ProcessHelper.h */, + ADACEBC4973F4FC0A6FEC68A /* RemoveRedundantMaterials.cpp */, + AD969BA482564C7FAA372F7C /* RemoveRedundantMaterials.h */, + FB4ABA17AF264257BDA4D921 /* RemoveVCProcess.cpp */, + ABDA70358E34432A8A4637F4 /* RemoveVCProcess.h */, + BD9A81E0E27E44718609615B /* SortByPTypeProcess.cpp */, + 16437E08A946431EB2EFA3E0 /* SortByPTypeProcess.h */, + A43641DC9C1B4B578BC40476 /* SplitLargeMeshes.cpp */, + D2EEB62ECBF749AA89146C66 /* SplitLargeMeshes.h */, + DF76D04D95E649BCBC15E64F /* TextureTransform.cpp */, + C5C3ED2BE50D4684994BD533 /* TextureTransform.h */, + 1A0AC303D18A48A69AB3BC03 /* TriangulateProcess.cpp */, + FB2510D46F504365A03EE8A8 /* TriangulateProcess.h */, + 0EF4F7A237F648C2809A8F31 /* ValidateDataStructure.cpp */, + 725DAD1CE04C4F64BDAB7037 /* ValidateDataStructure.h */, + ); + name = PostProcessing; + sourceTree = ""; + }; + DAFF6641A88441AFBE8B99B1 /* COB */ = { + isa = PBXGroup; + children = ( + C84DA0E6CE13493D833BA1C1 /* COBLoader.cpp */, + 445F70426FCC42F088405E86 /* COBLoader.h */, + 9E0572B45F1F4605BD5C919D /* COBScene.h */, + ); + name = COB; + sourceTree = ""; + }; + DB181885BFCC44F594A1FA01 /* Source Files */ = { + isa = PBXGroup; + children = ( + 705D30EE141A48F292783F0E /* Assimp.cpp */, + 7FBEA0111B65B11800D2115E /* Version.cpp */, + ); + name = "Source Files"; + sourceTree = ""; + }; + DD5B35196B184EFB820D1FBB /* CSM */ = { + isa = PBXGroup; + children = ( + 77908990BEF04D0881E8AE80 /* CSMLoader.cpp */, + 1BC6B0FE92DD4F38803BC17B /* CSMLoader.h */, + ); + name = CSM; + sourceTree = ""; + }; + EF7D37EB84AF45FC8BF47E7F /* MDL */ = { + isa = PBXGroup; + children = ( + F1A7BD0B5CAE48699FCAEBD1 /* MDLDefaultColorMap.h */, + D5F4108F03D7457EB641836B /* MDLFileData.h */, + AA92FFC8B06D4569AD9C4CB1 /* MDLLoader.cpp */, + E24E950227C848D3A759F5C2 /* MDLLoader.h */, + CEC69808E1844C23B95D3475 /* MDLMaterialLoader.cpp */, + ); + name = MDL; + sourceTree = ""; + }; + F0273EDFDBD34EDAA6678613 /* Q3D */ = { + isa = PBXGroup; + children = ( + C5178B3983F147F3B9BD8217 /* Q3DLoader.cpp */, + 76773A53296549FFA43956A1 /* Q3DLoader.h */, + ); + name = Q3D; + sourceTree = ""; + }; + F61A479614764D11AC3311A8 /* Poly2Tri */ = { + isa = PBXGroup; + children = ( + AE00939F150F413780C8AAD7 /* shapes.cc */, + EE545B58FA1246C792C6AD01 /* shapes.h */, + 50935A81362041BEADF18609 /* utils.h */, + B72D0BA3EF66439F8D582ED3 /* advancing_front.cc */, + DAE82F651F9E4D91A6A6C753 /* advancing_front.h */, + 849EC6315E4A4E5FA06521EA /* cdt.cc */, + 904A696E49D540C2A880792B /* cdt.h */, + 49E993CD86A346869AF473BC /* sweep.cc */, + 62E8551653634972ABBABCAD /* sweep.h */, + 5E10483FBE6D4F4594B460E0 /* sweep_context.cc */, + 267D593135514108B7DEF072 /* sweep_context.h */, + ); + name = Poly2Tri; + sourceTree = ""; + }; + F9261D592F00437EAFC663B5 /* MD2 */ = { + isa = PBXGroup; + children = ( + 21E21BE7CB364AC3AB81E54C /* MD2FileData.h */, + 49B655CCE1314D4E8A94B371 /* MD2Loader.cpp */, + 531FBC4210644C61954EA4C4 /* MD2Loader.h */, + FD84CFD1BD3E4AF4BA622BB8 /* MD2NormalTable.h */, + ); + name = MD2; + sourceTree = ""; + }; + FCFE51BCE7384933A972EDEE /* Header Files */ = { + isa = PBXGroup; + children = ( + 731205CAB88247C095E33412 /* Exporter.hpp */, + B54FBAAF061B40DBA3F48F83 /* IOStream.hpp */, + 86E296E459F94050ACBA3C63 /* IOSystem.hpp */, + B9DFF24FD63A4D9FAE213EED /* Importer.hpp */, + 69AFF47737244CE3BD1653CC /* ProgressHandler.hpp */, + C7B37CA474DF4CE7A5B0658E /* ai_assert.h */, + B441D87EE6ED4EBFB0586B66 /* anim.h */, + B05DC38593F04180B322360B /* camera.h */, + 2F34A6A3C4104625A52BF7C2 /* cexport.h */, + E1313C36045444619026E9FB /* cfileio.h */, + 267A74499024423A86150697 /* cimport.h */, + 0535CB113239433DA7CD7FDE /* color4.h */, + 079B3C75D1014265959C427D /* color4.inl */, + 90949C7A51E84D3595D71A6B /* config.h */, + 9761D873B9604504B9AD7CD5 /* defs.h */, + 4D82A29A8BBF44E69E026F84 /* importerdesc.h */, + 8E2108F568374F65ACE217D1 /* light.h */, + 05EA73C462244F1791039BFB /* material.h */, + 139DFC029C4C44B09952C645 /* material.inl */, + 10E9B0497D844A10BC759A09 /* matrix3x3.h */, + 073189BEE7A5466B9EE817D4 /* matrix3x3.inl */, + BA832069DF214327AE067503 /* matrix4x4.h */, + 4493838DDEE841BF96A0F008 /* matrix4x4.inl */, + E9ED3048A21E483F9C2721F4 /* mesh.h */, + 5F84BDD0D5D345A2BF1E08E1 /* metadata.h */, + 41C2F6D564924BF4ACE75CAC /* postprocess.h */, + 279D2A482FE9402A8F7EC441 /* quaternion.h */, + 97F52051AF4F478FA77AABBC /* quaternion.inl */, + 3B407EAF162843CBA46BC9D4 /* scene.h */, + AE1C2E2C9C424B3684AD9D4A /* texture.h */, + 56DA1CDC223747F4AFBAF953 /* types.h */, + FB1E84BE85A34F98A44BBB2B /* vector2.h */, + B6074B1E864740F787A97EA3 /* vector2.inl */, + 6D72952403D04713A6451654 /* vector3.h */, + 8D53CC35AAED4CE8B9710E04 /* vector3.inl */, + FC0801BA1F95494498A089AF /* version.h */, + ); + name = "Header Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7F79227F1AB43AC3005A8E5D /* assimp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7F7922911AB43AC3005A8E5D /* Build configuration list for PBXNativeTarget "assimp" */; + buildPhases = ( + 7F79229B1AB43AF4005A8E5D /* Run Script to build "revision.h" */, + 7F79227C1AB43AC3005A8E5D /* Sources */, + 7F79227D1AB43AC3005A8E5D /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = assimp; + productName = assimp; + productReference = 7F7922801AB43AC3005A8E5D /* libassimp.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9DE203BC835F4C81BCDF25CF /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 0700; + TargetAttributes = { + 7F79227F1AB43AC3005A8E5D = { + CreatedOnToolsVersion = 6.3; + }; + }; + }; + buildConfigurationList = 0C36C32B633D49CB92166176 /* Build configuration list for PBXProject "Assimp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = BCC52F1D5AF74E54A2D69524; + projectDirPath = ../..; + projectRoot = ""; + targets = ( + 7F79227F1AB43AC3005A8E5D /* assimp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 7F79229B1AB43AF4005A8E5D /* Run Script to build "revision.h" */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script to build \"revision.h\""; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "mkdir -p \"${DERIVED_FILE_DIR}\"\ncat \"${SRCROOT}/revision.h.in\" | sed \"s/@GIT_COMMIT_HASH@/`git rev-parse --short HEAD`/g\" | sed \"s/@GIT_BRANCH@/`git rev-parse --abbrev-ref HEAD`/g\" > \"${DERIVED_FILE_DIR}/revision.h\""; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7F79227C1AB43AC3005A8E5D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7F79242A1AB43E20005A8E5D /* 3DSConverter.cpp in Sources */, + 7F79242B1AB43E20005A8E5D /* 3DSExporter.cpp in Sources */, + 7F79242C1AB43E20005A8E5D /* 3DSLoader.cpp in Sources */, + 7F79242D1AB43E20005A8E5D /* ACLoader.cpp in Sources */, + 7F79242E1AB43E20005A8E5D /* ASELoader.cpp in Sources */, + 7F79242F1AB43E20005A8E5D /* ASEParser.cpp in Sources */, + 7F7924301AB43E20005A8E5D /* AssbinExporter.cpp in Sources */, + 7F7924311AB43E20005A8E5D /* AssbinLoader.cpp in Sources */, + 7F7924321AB43E20005A8E5D /* Assimp.cpp in Sources */, + 7F7924331AB43E20005A8E5D /* AssimpCExport.cpp in Sources */, + 7F7924351AB43E20005A8E5D /* AssxmlExporter.cpp in Sources */, + 7F7924361AB43E20005A8E5D /* B3DImporter.cpp in Sources */, + 7F7924371AB43E20005A8E5D /* BVHLoader.cpp in Sources */, + 7F7924381AB43E20005A8E5D /* BaseImporter.cpp in Sources */, + 7F7924391AB43E20005A8E5D /* BaseProcess.cpp in Sources */, + 7F79243A1AB43E20005A8E5D /* Bitmap.cpp in Sources */, + 7F79243B1AB43E20005A8E5D /* BlenderBMesh.cpp in Sources */, + 7F79243C1AB43E20005A8E5D /* BlenderDNA.cpp in Sources */, + 7F79243D1AB43E20005A8E5D /* BlenderLoader.cpp in Sources */, + 7F79243E1AB43E20005A8E5D /* BlenderModifier.cpp in Sources */, + 7F79243F1AB43E20005A8E5D /* BlenderScene.cpp in Sources */, + 7F7924401AB43E20005A8E5D /* BlenderTessellator.cpp in Sources */, + 7F7924411AB43E20005A8E5D /* COBLoader.cpp in Sources */, + 7F7924421AB43E20005A8E5D /* CSMLoader.cpp in Sources */, + 7F7924431AB43E20005A8E5D /* CalcTangentsProcess.cpp in Sources */, + 7F7924441AB43E20005A8E5D /* ColladaExporter.cpp in Sources */, + 7F7924451AB43E20005A8E5D /* ColladaLoader.cpp in Sources */, + 7F7924461AB43E20005A8E5D /* ColladaParser.cpp in Sources */, + 7F7924471AB43E20005A8E5D /* ComputeUVMappingProcess.cpp in Sources */, + 7F7924481AB43E20005A8E5D /* ConvertToLHProcess.cpp in Sources */, + 7F7924491AB43E20005A8E5D /* DXFLoader.cpp in Sources */, + 7F79244A1AB43E20005A8E5D /* DeboneProcess.cpp in Sources */, + 7F79244B1AB43E20005A8E5D /* DefaultIOStream.cpp in Sources */, + 7F79244C1AB43E20005A8E5D /* DefaultIOSystem.cpp in Sources */, + 7F7A93A81B65D0110094C4DA /* DDLNode.cpp in Sources */, + 7F79244D1AB43E20005A8E5D /* DefaultLogger.cpp in Sources */, + 7F79244E1AB43E20005A8E5D /* Exporter.cpp in Sources */, + 7F79244F1AB43E20005A8E5D /* FBXAnimation.cpp in Sources */, + 7F7924501AB43E20005A8E5D /* FBXBinaryTokenizer.cpp in Sources */, + 7F7924511AB43E20005A8E5D /* FBXConverter.cpp in Sources */, + 7F7924521AB43E20005A8E5D /* FBXDeformer.cpp in Sources */, + 7F7924531AB43E20005A8E5D /* FBXDocument.cpp in Sources */, + 7F7924541AB43E20005A8E5D /* FBXDocumentUtil.cpp in Sources */, + 7F7924551AB43E20005A8E5D /* FBXImporter.cpp in Sources */, + 7F7924561AB43E20005A8E5D /* FBXMaterial.cpp in Sources */, + 7F7924571AB43E20005A8E5D /* FBXMeshGeometry.cpp in Sources */, + 7F7924581AB43E20005A8E5D /* FBXModel.cpp in Sources */, + 7F7924591AB43E20005A8E5D /* FBXNodeAttribute.cpp in Sources */, + 7F79245A1AB43E20005A8E5D /* FBXParser.cpp in Sources */, + 7F79245B1AB43E20005A8E5D /* FBXProperties.cpp in Sources */, + 7F79245C1AB43E20005A8E5D /* FBXTokenizer.cpp in Sources */, + 7F79245D1AB43E20005A8E5D /* FBXUtil.cpp in Sources */, + 7F7A93A91B65D0110094C4DA /* OpenDDLParser.cpp in Sources */, + 7F79245E1AB43E20005A8E5D /* FindDegenerates.cpp in Sources */, + 7F79245F1AB43E20005A8E5D /* FindInstancesProcess.cpp in Sources */, + 7F7924601AB43E20005A8E5D /* FindInvalidDataProcess.cpp in Sources */, + 7F7924611AB43E20005A8E5D /* FixNormalsStep.cpp in Sources */, + 7F7924621AB43E20005A8E5D /* GenFaceNormalsProcess.cpp in Sources */, + 7F7924631AB43E20005A8E5D /* GenVertexNormalsProcess.cpp in Sources */, + 7F7924641AB43E20005A8E5D /* HMPLoader.cpp in Sources */, + 7F7924651AB43E20005A8E5D /* IFCBoolean.cpp in Sources */, + 7F7924661AB43E20005A8E5D /* IFCCurve.cpp in Sources */, + 7F7924671AB43E20005A8E5D /* IFCGeometry.cpp in Sources */, + 7F7924681AB43E20005A8E5D /* IFCLoader.cpp in Sources */, + 7F7924691AB43E20005A8E5D /* IFCMaterial.cpp in Sources */, + 7F79246A1AB43E20005A8E5D /* IFCOpenings.cpp in Sources */, + 7F79246B1AB43E20005A8E5D /* IFCProfile.cpp in Sources */, + 7FBEA0121B65B11800D2115E /* Version.cpp in Sources */, + 7F79246C1AB43E20005A8E5D /* IFCReaderGen.cpp in Sources */, + 7F79246D1AB43E20005A8E5D /* IFCUtil.cpp in Sources */, + 7F79246E1AB43E20005A8E5D /* IRRLoader.cpp in Sources */, + 7F79246F1AB43E20005A8E5D /* IRRMeshLoader.cpp in Sources */, + 7F7924701AB43E20005A8E5D /* IRRShared.cpp in Sources */, + 7F7924711AB43E20005A8E5D /* Importer.cpp in Sources */, + 7F7924721AB43E20005A8E5D /* ImporterRegistry.cpp in Sources */, + 7F7924731AB43E20005A8E5D /* ImproveCacheLocality.cpp in Sources */, + 7F7924741AB43E20005A8E5D /* JoinVerticesProcess.cpp in Sources */, + 7F7924751AB43E20005A8E5D /* LWOAnimation.cpp in Sources */, + 7F7924761AB43E20005A8E5D /* LWOBLoader.cpp in Sources */, + 7F7924771AB43E20005A8E5D /* LWOLoader.cpp in Sources */, + 7F7924781AB43E20005A8E5D /* LWOMaterial.cpp in Sources */, + 7F7924791AB43E20005A8E5D /* LWSLoader.cpp in Sources */, + 7F79247A1AB43E20005A8E5D /* LimitBoneWeightsProcess.cpp in Sources */, + 7F79247B1AB43E20005A8E5D /* MD2Loader.cpp in Sources */, + 7F79247C1AB43E20005A8E5D /* MD3Loader.cpp in Sources */, + 7F79247D1AB43E20005A8E5D /* MD5Loader.cpp in Sources */, + 7F79247E1AB43E20005A8E5D /* MD5Parser.cpp in Sources */, + 7F79247F1AB43E20005A8E5D /* MDCLoader.cpp in Sources */, + 7F7924801AB43E20005A8E5D /* MDLLoader.cpp in Sources */, + 7F7924811AB43E20005A8E5D /* MDLMaterialLoader.cpp in Sources */, + 7F7924821AB43E20005A8E5D /* MS3DLoader.cpp in Sources */, + 7FBE9FEB1B65AC1200D2115E /* OpenGEXImporter.cpp in Sources */, + 7F7924831AB43E20005A8E5D /* MakeVerboseFormat.cpp in Sources */, + 7F7924841AB43E20005A8E5D /* MaterialSystem.cpp in Sources */, + 7F7924851AB43E20005A8E5D /* NDOLoader.cpp in Sources */, + 7F7924861AB43E20005A8E5D /* NFFLoader.cpp in Sources */, + 7F7924871AB43E20005A8E5D /* OFFLoader.cpp in Sources */, + 7F7924881AB43E20005A8E5D /* ObjExporter.cpp in Sources */, + 7F7924891AB43E20005A8E5D /* ObjFileImporter.cpp in Sources */, + 7F79248A1AB43E20005A8E5D /* ObjFileMtlImporter.cpp in Sources */, + 7F79248B1AB43E20005A8E5D /* ObjFileParser.cpp in Sources */, + 7F79248C1AB43E20005A8E5D /* OgreBinarySerializer.cpp in Sources */, + 7F79248D1AB43E20005A8E5D /* OgreImporter.cpp in Sources */, + 7F79248E1AB43E20005A8E5D /* OgreMaterial.cpp in Sources */, + 7F79248F1AB43E20005A8E5D /* OgreStructs.cpp in Sources */, + 7F7924901AB43E20005A8E5D /* OgreXmlSerializer.cpp in Sources */, + 7F7924911AB43E20005A8E5D /* OptimizeGraph.cpp in Sources */, + 7F7924921AB43E20005A8E5D /* OptimizeMeshes.cpp in Sources */, + 7F7924931AB43E20005A8E5D /* PlyExporter.cpp in Sources */, + 7F7924941AB43E20005A8E5D /* PlyLoader.cpp in Sources */, + 7F7924951AB43E20005A8E5D /* PlyParser.cpp in Sources */, + 7F7924961AB43E20005A8E5D /* PostStepRegistry.cpp in Sources */, + 7F7924971AB43E20005A8E5D /* PretransformVertices.cpp in Sources */, + 7F7924981AB43E20005A8E5D /* ProcessHelper.cpp in Sources */, + 7F7A93AA1B65D0110094C4DA /* Value.cpp in Sources */, + 7F7924991AB43E20005A8E5D /* Q3BSPFileImporter.cpp in Sources */, + 7F79249A1AB43E20005A8E5D /* Q3BSPFileParser.cpp in Sources */, + 7F79249B1AB43E20005A8E5D /* Q3BSPZipArchive.cpp in Sources */, + 7F79249C1AB43E20005A8E5D /* Q3DLoader.cpp in Sources */, + 7F79249D1AB43E20005A8E5D /* RawLoader.cpp in Sources */, + 7F79249E1AB43E20005A8E5D /* RemoveComments.cpp in Sources */, + 7F79249F1AB43E20005A8E5D /* RemoveRedundantMaterials.cpp in Sources */, + 7F7924A01AB43E20005A8E5D /* RemoveVCProcess.cpp in Sources */, + 7F7924A11AB43E20005A8E5D /* SGSpatialSort.cpp in Sources */, + 7F7924A21AB43E20005A8E5D /* SMDLoader.cpp in Sources */, + 7F7924A31AB43E20005A8E5D /* STEPFileEncoding.cpp in Sources */, + 7F7924A41AB43E20005A8E5D /* STEPFileReader.cpp in Sources */, + 7F7924A51AB43E20005A8E5D /* STLExporter.cpp in Sources */, + 7FBE9FEA1B65AC1200D2115E /* OpenGEXExporter.cpp in Sources */, + 7F7924A61AB43E20005A8E5D /* STLLoader.cpp in Sources */, + 7F7924A71AB43E20005A8E5D /* SceneCombiner.cpp in Sources */, + 7F7924A81AB43E20005A8E5D /* ScenePreprocessor.cpp in Sources */, + 7F7924A91AB43E20005A8E5D /* SkeletonMeshBuilder.cpp in Sources */, + 7F7924AA1AB43E20005A8E5D /* SortByPTypeProcess.cpp in Sources */, + 7F7924AB1AB43E20005A8E5D /* SpatialSort.cpp in Sources */, + 7F7924AC1AB43E20005A8E5D /* SplitByBoneCountProcess.cpp in Sources */, + 7F7924AD1AB43E20005A8E5D /* SplitLargeMeshes.cpp in Sources */, + 7F7924AE1AB43E20005A8E5D /* StandardShapes.cpp in Sources */, + 7F7924AF1AB43E20005A8E5D /* Subdivision.cpp in Sources */, + 7F7924B01AB43E20005A8E5D /* TargetAnimation.cpp in Sources */, + 7F7924B11AB43E20005A8E5D /* TerragenLoader.cpp in Sources */, + 7F7924B21AB43E20005A8E5D /* TextureTransform.cpp in Sources */, + 7F7924B31AB43E20005A8E5D /* TriangulateProcess.cpp in Sources */, + 7F7924B41AB43E20005A8E5D /* UnrealLoader.cpp in Sources */, + 7F7924B51AB43E20005A8E5D /* ValidateDataStructure.cpp in Sources */, + 7F7924B61AB43E20005A8E5D /* VertexTriangleAdjacency.cpp in Sources */, + 7F7924B71AB43E20005A8E5D /* XFileExporter.cpp in Sources */, + 7F7924B81AB43E20005A8E5D /* XFileImporter.cpp in Sources */, + 7F7924B91AB43E20005A8E5D /* XFileParser.cpp in Sources */, + 7F7924BA1AB43E20005A8E5D /* XGLLoader.cpp in Sources */, + 7F7924BB1AB43E20005A8E5D /* ConvertUTF.c in Sources */, + 7F7924BC1AB43E20005A8E5D /* clipper.cpp in Sources */, + 7F7924BD1AB43E20005A8E5D /* irrXML.cpp in Sources */, + 7F7924BE1AB43E20005A8E5D /* shapes.cc in Sources */, + 7F7924BF1AB43E20005A8E5D /* advancing_front.cc in Sources */, + 7F7924C01AB43E20005A8E5D /* cdt.cc in Sources */, + 7F7924C11AB43E20005A8E5D /* sweep.cc in Sources */, + 7F7924C21AB43E20005A8E5D /* sweep_context.cc in Sources */, + 7F7924C31AB43E20005A8E5D /* ioapi.c in Sources */, + 7F7924C41AB43E20005A8E5D /* unzip.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 137567A2412C45B8A269E344 /* RelWithDebInfo */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; + MACH_O_TYPE = staticlib; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + }; + name = RelWithDebInfo; + }; + 7F7922921AB43AC3005A8E5D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++98"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_COMPATIBILITY_VERSION = 3.0.0; + DYLIB_CURRENT_VERSION = 3.1.1; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + assimp_EXPORTS, + ASSIMP_BUILD_BOOST_WORKAROUND, + ASSIMP_BUILD_NO_OWN_ZLIB, + ASSIMP_BUILD_NO_C4D_IMPORTER, + ASSIMP_BUILD_DLL_EXPORT, + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + }; + name = Debug; + }; + 7F7922931AB43AC3005A8E5D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++98"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_COMPATIBILITY_VERSION = 3.0.0; + DYLIB_CURRENT_VERSION = 3.1.1; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = fast; + GCC_PREPROCESSOR_DEFINITIONS = ( + assimp_EXPORTS, + ASSIMP_BUILD_BOOST_WORKAROUND, + ASSIMP_BUILD_NO_OWN_ZLIB, + ASSIMP_BUILD_NO_C4D_IMPORTER, + ASSIMP_BUILD_DLL_EXPORT, + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7F7922941AB43AC3005A8E5D /* MinSizeRel */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++98"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_COMPATIBILITY_VERSION = 3.0.0; + DYLIB_CURRENT_VERSION = 3.1.1; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + assimp_EXPORTS, + ASSIMP_BUILD_BOOST_WORKAROUND, + ASSIMP_BUILD_NO_OWN_ZLIB, + ASSIMP_BUILD_NO_C4D_IMPORTER, + ASSIMP_BUILD_DLL_EXPORT, + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + VALIDATE_PRODUCT = YES; + }; + name = MinSizeRel; + }; + 7F7922951AB43AC3005A8E5D /* RelWithDebInfo */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++98"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_COMPATIBILITY_VERSION = 3.0.0; + DYLIB_CURRENT_VERSION = 3.1.1; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + assimp_EXPORTS, + ASSIMP_BUILD_BOOST_WORKAROUND, + ASSIMP_BUILD_NO_OWN_ZLIB, + ASSIMP_BUILD_NO_C4D_IMPORTER, + ASSIMP_BUILD_DLL_EXPORT, + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + VALIDATE_PRODUCT = YES; + }; + name = RelWithDebInfo; + }; + 9604718722A94CBB9F87A9D8 /* MinSizeRel */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; + MACH_O_TYPE = staticlib; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + }; + name = MinSizeRel; + }; + C58F2FA1D18E452FBFD3B286 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ENABLE_TESTABILITY = YES; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + MACH_O_TYPE = staticlib; + ONLY_ACTIVE_ARCH = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + }; + name = Debug; + }; + DB0088F8DB7C490CBA3CCB90 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; + MACH_O_TYPE = staticlib; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0C36C32B633D49CB92166176 /* Build configuration list for PBXProject "Assimp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C58F2FA1D18E452FBFD3B286 /* Debug */, + DB0088F8DB7C490CBA3CCB90 /* Release */, + 9604718722A94CBB9F87A9D8 /* MinSizeRel */, + 137567A2412C45B8A269E344 /* RelWithDebInfo */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 7F7922911AB43AC3005A8E5D /* Build configuration list for PBXNativeTarget "assimp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7F7922921AB43AC3005A8E5D /* Debug */, + 7F7922931AB43AC3005A8E5D /* Release */, + 7F7922941AB43AC3005A8E5D /* MinSizeRel */, + 7F7922951AB43AC3005A8E5D /* RelWithDebInfo */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9DE203BC835F4C81BCDF25CF /* Project object */; +} diff --git a/workspaces/xcode6/Assimp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/workspaces/xcode6/Assimp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..0abcc1fa5 --- /dev/null +++ b/workspaces/xcode6/Assimp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/workspaces/xcode6/Assimp.xcodeproj/xcshareddata/xcschemes/assimp.xcscheme b/workspaces/xcode6/Assimp.xcodeproj/xcshareddata/xcschemes/assimp.xcscheme new file mode 100644 index 000000000..99aae1cbb --- /dev/null +++ b/workspaces/xcode6/Assimp.xcodeproj/xcshareddata/xcschemes/assimp.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +