Browse Source

Merge remote-tracking branch 'origin'

Conflicts:
	code/C4DImporter.cpp
	code/OgreImporter.h
abma 10 years ago
parent
commit
8c45a4dc3b
95 changed files with 26953 additions and 4528 deletions
  1. 5 1
      .gitignore
  2. 30 21
      .travis.yml
  3. 8 3
      CMakeLists.txt
  4. 5 0
      CREDITS
  5. 22 27
      Readme.md
  6. 16 0
      cmake-modules/MinGW_x86_64.cmake
  7. 2 2
      code/3DSExporter.cpp
  8. 1 1
      code/AssbinExporter.cpp
  9. 1 1
      code/AssxmlExporter.cpp
  10. 17 1
      code/BlenderIntermediate.h
  11. 10 7
      code/BlenderLoader.cpp
  12. 2 0
      code/BlobIOSystem.h
  13. 1 1
      code/C4DImporter.cpp
  14. 26 3
      code/CMakeLists.txt
  15. 6 2
      code/COBLoader.cpp
  16. 1 1
      code/ColladaExporter.cpp
  17. 1 0
      code/ColladaHelper.h
  18. 2 2
      code/ColladaLoader.cpp
  19. 41 7
      code/ColladaParser.cpp
  20. 128 15
      code/Exporter.cpp
  21. 124 34
      code/FBXConverter.cpp
  22. 5 5
      code/FBXDocument.h
  23. 106 0
      code/FBXParser.cpp
  24. 3 0
      code/FBXParser.h
  25. 5 2
      code/FBXProperties.cpp
  26. 13 0
      code/GenericProperty.h
  27. 2 2
      code/IFCCurve.cpp
  28. 95 76
      code/IFCGeometry.cpp
  29. 6 3
      code/IFCLoader.cpp
  30. 1091 1464
      code/IFCReaderGen.cpp
  31. 1278 1270
      code/IFCReaderGen.h
  32. 1 1
      code/IFCUtil.cpp
  33. 1 0
      code/IFCUtil.h
  34. 53 47
      code/ImporterRegistry.cpp
  35. 1 1
      code/ObjExporter.cpp
  36. 520 519
      code/ObjFileImporter.cpp
  37. 39 37
      code/ObjFileImporter.h
  38. 486 486
      code/ObjFileParser.cpp
  39. 59 59
      code/ObjFileParser.h
  40. 866 0
      code/OpenGEXImporter.cpp
  41. 186 0
      code/OpenGEXImporter.h
  42. 265 0
      code/OpenGEXStructs.h
  43. 6 1
      code/ParsingUtils.h
  44. 2 2
      code/PlyExporter.cpp
  45. 46 27
      code/PlyLoader.cpp
  46. 2 2
      code/STLExporter.cpp
  47. 3 1
      code/SceneCombiner.cpp
  48. 3 0
      code/Subdivision.cpp
  49. 28 9
      code/XFileExporter.cpp
  50. 8 2
      code/XFileExporter.h
  51. 7 1
      code/XGLLoader.cpp
  52. 11 0
      code/XGLLoader.h
  53. 17 0
      code/fast_atof.h
  54. 64 0
      contrib/openddlparser/CMakeLists.txt
  55. 111 0
      contrib/openddlparser/README.md
  56. 184 0
      contrib/openddlparser/code/DDLNode.cpp
  57. 911 0
      contrib/openddlparser/code/OpenDDLParser.cpp
  58. 297 0
      contrib/openddlparser/code/Value.cpp
  59. 90 0
      contrib/openddlparser/include/openddlparser/DDLNode.h
  60. 210 0
      contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
  61. 131 0
      contrib/openddlparser/include/openddlparser/OpenDDLParser.h
  62. 250 0
      contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
  63. 105 0
      contrib/openddlparser/include/openddlparser/Value.h
  64. 46 46
      include/assimp/Compiler/pushpack1.h
  65. 185 9
      include/assimp/Exporter.hpp
  66. 11 0
      include/assimp/config.h
  67. 53 44
      port/jassimp/build.xml
  68. 13 0
      port/jassimp/jassimp-native/Android.mk
  69. 118 28
      port/jassimp/jassimp-native/src/jassimp.cpp
  70. 17 0
      port/jassimp/jassimp-native/src/jassimp.h
  71. 8 4
      port/jassimp/jassimp/src/jassimp/AiMesh.java
  72. 10 11
      port/jassimp/jassimp/src/jassimp/AiNodeAnim.java
  73. 59 1
      port/jassimp/jassimp/src/jassimp/Jassimp.java
  74. 3 2
      scripts/IFCImporter/ExpressReader.py
  75. 5 4
      scripts/IFCImporter/entitylist.txt
  76. 9571 0
      scripts/IFCImporter/schema.exp
  77. 0 33
      test/RunSingleUnitTestSuite.bat
  78. 0 94
      test/RunUnitTestSuite.bat
  79. BIN
      test/models-nonbsd/FBX/2013_BINARY/anims_with_full_rotations_between_keys.fbx
  80. BIN
      test/models-nonbsd/FBX/2013_BINARY/multiple_animations_test.fbx
  81. 754 0
      test/models-nonbsd/PLY/ant-half.ply
  82. 165 0
      test/models-nonbsd/PLY/ant-half.ply.license
  83. BIN
      test/models/BLEND/BlenderDefault_271.blend
  84. 7561 0
      test/models/Collada/anims_with_full_rotations_between_keys.DAE
  85. 95 0
      test/models/OpenGEX/Example.ogex
  86. 50 52
      test/regression/README
  87. BIN
      test/regression/db.zip
  88. 17 15
      test/regression/gen_db.py
  89. 22 18
      test/regression/run.py
  90. 2 2
      test/regression/settings.py
  91. 2 4
      test/regression/utils.py
  92. 1 1
      tools/assimp_cmd/CMakeLists.txt
  93. 37 14
      tools/assimp_cmd/CompareDump.cpp
  94. 124 0
      workspaces/Android-NDK/jni/Android.mk
  95. 8 0
      workspaces/Android-NDK/jni/Application.mk

+ 5 - 1
.gitignore

@@ -10,7 +10,7 @@ build
 # Output
 # Output
 bin/
 bin/
 lib/
 lib/
-contrib/
+
 
 
 # Generated
 # Generated
 assimp.pc
 assimp.pc
@@ -54,3 +54,7 @@ tools/assimp_view/assimp_viewer.vcxproj.user
 
 
 # Unix editor backups
 # Unix editor backups
 *~
 *~
+test/gtest/src/gtest-stamp/gtest-gitinfo.txt
+test/gtest/src/gtest-stamp/gtest-gitclone-lastrun.txt
+Assimp.opensdf
+contrib/zlib/CTestTestfile.cmake

+ 30 - 21
.travis.yml

@@ -1,16 +1,22 @@
 before_install:
 before_install:
+  - sudo apt-get update -qq
   - sudo apt-get install cmake python3
   - sudo apt-get install cmake python3
+  - if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
+  - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
+
+branches:
+  only:
+    - master
 
 
 env:
 env:
-    matrix:
+  global:
+    - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
+  matrix:
     - LINUX=1 TRAVIS_NO_EXPORT=YES
     - LINUX=1 TRAVIS_NO_EXPORT=YES
     - LINUX=1 TRAVIS_NO_EXPORT=NO
     - LINUX=1 TRAVIS_NO_EXPORT=NO
-    - LINUX=1 TRAVIS_STATIC_BUILD=ON
-    - LINUX=1 TRAVIS_STATIC_BUILD=OFF
-    - WINDOWS=1 TRAVIS_NO_EXPORT=YES
-    - WINDOWS=1 TRAVIS_NO_EXPORT=NO
-    - WINDOWS=1 TRAVIS_STATIC_BUILD=ON
-    - WINDOWS=1 TRAVIS_STATIC_BUILD=OFF
+    - LINUX=1 SHARED_BUILD=ON
+    - LINUX=1 SHARED_BUILD=OFF
+    - ANDROID=1
 
 
 language: cpp
 language: cpp
 
 
@@ -19,19 +25,22 @@ compiler:
   - clang
   - clang
 
 
 install:
 install:
-  - if [ $WINDOWS ]; then travis_retry sudo apt-get install -q -y gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64; fi 
+  - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
 
 
 script:
 script:
-  - cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD
-  - make
-  - sudo make install
-  - sudo ldconfig
-  - cd test/unit
-  - ../../bin/unit
-  - cd ../regression
-  - chmod 755 run.py
-  - ./run.py
-  - echo "=========================================================="
-  - echo "REGRESSION TEST FAILS (results/run_regression_suite_failures.csv)"
-  - cat ../results/run_regression_suite_failures.csv
-
+  - if [ $ANDROID ]; then 
+    ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni ;
+    else
+    cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -DBUILD_SHARED_LIBS=$SHARED_BUILD ;
+    make ;
+    sudo make install ;
+    sudo ldconfig ;
+    cd test/unit ;
+    ../../bin/unit ;
+    cd ../regression ;
+    chmod 755 run.py ;
+    ./run.py ;
+    echo "==========================================================" ;
+    echo "REGRESSION TEST FAILURES (results/run_regression_suite_failures.csv)" ;
+    cat ../results/run_regression_suite_failures.csv;
+    fi

+ 8 - 3
CMakeLists.txt

@@ -1,6 +1,12 @@
 cmake_minimum_required( VERSION 2.8 )
 cmake_minimum_required( VERSION 2.8 )
 PROJECT( Assimp )
 PROJECT( Assimp )
 
 
+option(BUILD_SHARED_LIBS "Build package with shared libraries." ON)
+if(NOT BUILD_SHARED_LIBS)
+        #set(CMAKE_EXE_LINKER_FLAGS "-static")
+	set(LINK_SEARCH_START_STATIC TRUE)
+endif(NOT BUILD_SHARED_LIBS)
+
 # Define here the needed parameters
 # Define here the needed parameters
 set (ASSIMP_VERSION_MAJOR 3)
 set (ASSIMP_VERSION_MAJOR 3)
 set (ASSIMP_VERSION_MINOR 1)
 set (ASSIMP_VERSION_MINOR 1)
@@ -11,6 +17,8 @@ set (PROJECT_VERSION "${ASSIMP_VERSION}")
 
 
 set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources")
 set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources")
 
 
+add_definitions( -DOPENDDL_NO_USE_CPP11 )
+
 # Get the current working branch
 # Get the current working branch
 execute_process(
 execute_process(
     COMMAND git rev-parse --abbrev-ref HEAD
     COMMAND git rev-parse --abbrev-ref HEAD
@@ -86,9 +94,6 @@ SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
 
 
 SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
 SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
 
 
-# Allow the user to build a shared or static library
-option ( BUILD_SHARED_LIBS "Build a shared version of the library" ON )
-
 # Only generate this target if no higher-level project already has
 # Only generate this target if no higher-level project already has
 IF (NOT TARGET uninstall)
 IF (NOT TARGET uninstall)
     # add make uninstall capability
     # add make uninstall capability

+ 5 - 0
CREDITS

@@ -151,3 +151,8 @@ Ogre Binary format support
 
 
 - Filip Wasil, Tieto Poland Sp. z o.o.
 - Filip Wasil, Tieto Poland Sp. z o.o.
 Android JNI asset extraction support
 Android JNI asset extraction support
+
+- Richard Steffen
+Contributed X File exporter
+Contributed ExportProperties interface
+

+ 22 - 27
Readme.md

@@ -1,18 +1,25 @@
 Open Asset Import Library (assimp) 
 Open Asset Import Library (assimp) 
 ========
 ========
 
 
-Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
+Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
 
 
-This is the development trunk of assimp containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
+APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
 
 
-[open3mod](https://github.com/acgessler/open3mod) is an Open Source 3D model viewer based off Assimp's import and export abilities.
+Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
+
+This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status is:
+
+[![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
+
+__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
 
 
 #### Supported file formats ####
 #### Supported file formats ####
 
 
-The library provides importers for a lot of file formats, including:
+A full list [is here](http://assimp.sourceforge.net/main_features_formats.html).
+__Importers__:
 
 
 - 3DS
 - 3DS
-- BLEND (Blender 3D)
+- BLEND (Blender)
 - DAE/Collada
 - DAE/Collada
 - FBX
 - FBX
 - IFC-STEP 
 - IFC-STEP 
@@ -46,13 +53,13 @@ The library provides importers for a lot of file formats, including:
 - Ogre Binary
 - Ogre Binary
 - Ogre XML
 - Ogre XML
 - Q3D
 - Q3D
-- ASSBIN (Assimp scene serialization)
+- ASSBIN (Assimp custom format)
  
  
-Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
+Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
 
 
 - C4D (https://github.com/acgessler/assimp-cinema4d)
 - C4D (https://github.com/acgessler/assimp-cinema4d)
 
 
-Exporters include:
+__Exporters__:
 
 
 - DAE (Collada)
 - DAE (Collada)
 - STL
 - STL
@@ -63,23 +70,21 @@ Exporters include:
 - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
 - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
 - ASSBIN
 - ASSBIN
 	
 	
-See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
+### Building ###
+
 
 
+Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
 
 
 
 
 #### Repository structure ####
 #### Repository structure ####
 
 
 
 
-Open Asset Import Library is implemented in C++ (but provides both a C and a 
-C++ish interface). The directory structure is:
+Open Asset Import Library is implemented in C++. The directory structure is:
 
 
-	/bin		Folder for binaries, only used on Windows
 	/code		Source code
 	/code		Source code
 	/contrib	Third-party libraries
 	/contrib	Third-party libraries
 	/doc		Documentation (doxysource and pre-compiled docs)
 	/doc		Documentation (doxysource and pre-compiled docs)
 	/include	Public header C and C++ header files
 	/include	Public header C and C++ header files
-	/lib		Static library location for Windows
-	/obj		Object file location for Windows
 	/scripts 	Scripts used to generate the loading code for some formats
 	/scripts 	Scripts used to generate the loading code for some formats
 	/port		Ports to other languages and scripts to maintain those.
 	/port		Ports to other languages and scripts to maintain those.
 	/test		Unit- and regression tests, test suite of models
 	/test		Unit- and regression tests, test suite of models
@@ -90,24 +95,15 @@ C++ish interface). The directory structure is:
 			CMake has superseeded all legacy build options!)
 			CMake has superseeded all legacy build options!)
 
 
 
 
-
-### Building ###
-
-
-Take a look into the `INSTALL` file. Our build system is CMake, if you already used CMake before there is a good chance you know what to do.
-
-
 ### Where to get help ###
 ### Where to get help ###
 
 
 
 
 For more information, visit [our website](http://assimp.sourceforge.net/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
 For more information, visit [our website](http://assimp.sourceforge.net/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
 (CHMs for Windows are included in some release packages and should be located right here in the root folder).
 (CHMs for Windows are included in some release packages and should be located right here in the root folder).
 
 
-If the documentation doesn't solve your problems, 
-[try our forums at SF.net](http://sourceforge.net/p/assimp/discussion/817654) or ask on
-[StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
+If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
 
 
-For development discussions, there is also a mailing list, _assimp-discussions_
+For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
   [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) 
   [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) 
 
 
 ### Contributing ###
 ### Contributing ###
@@ -115,10 +111,9 @@ For development discussions, there is also a mailing list, _assimp-discussions_
 Contributions to assimp are highly appreciated. The easiest way to get involved is to submit 
 Contributions to assimp are highly appreciated. The easiest way to get involved is to submit 
 a pull request with your changes against the main repository's `master` branch.
 a pull request with your changes against the main repository's `master` branch.
 
 
-
 ### License ###
 ### License ###
 
 
-Our license is based on the modified, __3-clause BSD__-License, which is very liberal. 
+Our license is based on the modified, __3-clause BSD__-License. 
 
 
 An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - 
 An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - 
 and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
 and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.

+ 16 - 0
cmake-modules/MinGW_x86_64.cmake

@@ -0,0 +1,16 @@
+# this one sets internal to crosscompile (in theory)
+SET(CMAKE_SYSTEM_NAME Windows)
+
+# the minimalistic settings
+SET(CMAKE_C_COMPILER "/usr/bin/x86_64-w64-mingw32-gcc")
+SET(CMAKE_CXX_COMPILER "/usr/bin/x86_64-w64-mingw32-g++")
+SET(CMAKE_RC_COMPILER "/usr/bin/x86_64-w64-mingw32-windres")
+
+# where is the target (so called staging) environment
+SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
+
+# search for programs in the build host directories (default BOTH)
+#SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+# for libraries and headers in the target directories
+SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

+ 2 - 2
code/3DSExporter.cpp

@@ -147,7 +147,7 @@ namespace {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
-void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
 	boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
 	if(!outfile) {
 	if(!outfile) {
@@ -191,8 +191,8 @@ Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, c
 
 
 	{
 	{
 		ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
 		ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
-		WriteMeshes();
 		WriteMaterials();
 		WriteMaterials();
+		WriteMeshes();
 
 
 		{
 		{
 			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
 			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);

+ 1 - 1
code/AssbinExporter.cpp

@@ -757,7 +757,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
 		}
 		}
 	};
 	};
 
 
-void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	AssbinExport exporter;
 	AssbinExport exporter;
 	exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
 	exporter.WriteBinaryDump( pFile, pIOSystem, pScene );

+ 1 - 1
code/AssxmlExporter.cpp

@@ -623,7 +623,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
 
 
 } // end of namespace AssxmlExport
 } // end of namespace AssxmlExport
 
 
-void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	IOStream * out = pIOSystem->Open( pFile, "wt" );
 	IOStream * out = pIOSystem->Open( pFile, "wt" );
 	if (!out) return;
 	if (!out) return;

+ 17 - 1
code/BlenderIntermediate.h

@@ -123,6 +123,16 @@ namespace Blender {
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #	pragma warning(disable:4351)
 #	pragma warning(disable:4351)
 #endif
 #endif
+
+	struct ObjectCompare {
+		bool operator() (const Object* left, const Object* right) const {
+			return strcmp(left->id.name, right->id.name) == -1;
+		}
+	};
+
+	// When keeping objects in sets, sort them by their name.
+	typedef std::set<const Object*, ObjectCompare> ObjectSet;
+
 	// --------------------------------------------------------------------
 	// --------------------------------------------------------------------
 	/** ConversionData acts as intermediate storage location for
 	/** ConversionData acts as intermediate storage location for
 	 *  the various ConvertXXX routines in BlenderImporter.*/
 	 *  the various ConvertXXX routines in BlenderImporter.*/
@@ -135,7 +145,13 @@ namespace Blender {
 			, db(db)
 			, db(db)
 		{}
 		{}
 
 
-		std::set<const Object*> objects;
+		struct ObjectCompare {
+			bool operator() (const Object* left, const Object* right) const {
+				return strcmp(left->id.name, right->id.name) == -1;
+			}
+		};
+
+		ObjectSet objects;
 
 
 		TempArray <std::vector, aiMesh> meshes;
 		TempArray <std::vector, aiMesh> meshes;
 		TempArray <std::vector, aiCamera> cameras;
 		TempArray <std::vector, aiCamera> cameras;

+ 10 - 7
code/BlenderLoader.cpp

@@ -561,24 +561,26 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 		if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
 		if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
 
 
 			if (index == static_cast<unsigned int>( -1 )) {
 			if (index == static_cast<unsigned int>( -1 )) {
-
-				// ok, we need to add a dedicated default material for some poor material-less meshes
+				// Setup a default material.
 				boost::shared_ptr<Material> p(new Material());
 				boost::shared_ptr<Material> p(new Material());
+				ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name)-2);
 				strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
 				strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
 
 
+				// Note: MSVC11 does not zero-initialize Material here, although it should.
+				// Thus all relevant fields should be explicitly initialized. We cannot add
+				// a default constructor to Material since the DNA codegen does not support
+				// parsing it.
 				p->r = p->g = p->b = 0.6f;
 				p->r = p->g = p->b = 0.6f;
 				p->specr = p->specg = p->specb = 0.6f;
 				p->specr = p->specg = p->specb = 0.6f;
 				p->ambr = p->ambg = p->ambb = 0.0f;
 				p->ambr = p->ambg = p->ambb = 0.0f;
 				p->mirr = p->mirg = p->mirb = 0.0f;
 				p->mirr = p->mirg = p->mirb = 0.0f;
 				p->emit = 0.f;
 				p->emit = 0.f;
 				p->alpha = 0.f;
 				p->alpha = 0.f;
-
-				// XXX add more / or add default c'tor to Material
+				p->har = 0;
 
 
 				index = static_cast<unsigned int>( conv_data.materials_raw.size() );
 				index = static_cast<unsigned int>( conv_data.materials_raw.size() );
 				conv_data.materials_raw.push_back(p);
 				conv_data.materials_raw.push_back(p);
-
-				LogInfo("Adding default material ...");
+				LogInfo("Adding default material");
 			}
 			}
 			mesh->mMaterialIndex = index;
 			mesh->mMaterialIndex = index;
 		}
 		}
@@ -593,6 +595,7 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 	
 	
 		aiMaterial* mout = new aiMaterial();
 		aiMaterial* mout = new aiMaterial();
 		conv_data.materials->push_back(mout);
 		conv_data.materials->push_back(mout);
+		// For any new material field handled here, the default material above must be updated with an appropriate default value.
 
 
 		// set material name
 		// set material name
 		aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
 		aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
@@ -1046,7 +1049,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
 aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform)
 aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform)
 {
 {
 	std::deque<const Object*> children;
 	std::deque<const Object*> children;
-	for(std::set<const Object*>::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
+	for(ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
 		const Object* object = *it;
 		const Object* object = *it;
 		if (object->parent == obj) {
 		if (object->parent == obj) {
 			children.push_back(object);
 			children.push_back(object);

+ 2 - 0
code/BlobIOSystem.h

@@ -129,9 +129,11 @@ public:
 		{
 		{
 		case aiOrigin_CUR:
 		case aiOrigin_CUR:
 			cursor += pOffset;
 			cursor += pOffset;
+			break;
 
 
 		case aiOrigin_END:
 		case aiOrigin_END:
 			cursor = file_size - pOffset;
 			cursor = file_size - pOffset;
+			break;
 
 
 		case aiOrigin_SET:
 		case aiOrigin_SET:
 			cursor = pOffset;
 			cursor = pOffset;

+ 1 - 1
code/C4DImporter.cpp

@@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  C4DImporter.cpp
 /** @file  C4DImporter.cpp
  *  @brief Implementation of the Cinema4D importer class.
  *  @brief Implementation of the Cinema4D importer class.
  */
  */
-
+#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
 
 
 // no #ifdefing here, Cinema4D support is carried out in a branch of assimp
 // no #ifdefing here, Cinema4D support is carried out in a branch of assimp
 // where it is turned on in the CMake settings. 
 // where it is turned on in the CMake settings. 

+ 26 - 3
code/CMakeLists.txt

@@ -266,8 +266,6 @@ SET( LWS_SRCS
 )
 )
 SOURCE_GROUP( LWS FILES ${LWS_SRCS})
 SOURCE_GROUP( LWS FILES ${LWS_SRCS})
 
 
-
-
 SET( MD2_SRCS
 SET( MD2_SRCS
 	MD2FileData.h
 	MD2FileData.h
 	MD2Loader.cpp
 	MD2Loader.cpp
@@ -361,6 +359,13 @@ SET( Ogre_SRCS
 )
 )
 SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
 SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
 
 
+SET( OpenGEX_SRCS
+    OpenGEXImporter.cpp
+    OpenGEXImporter.h
+    OpenGEXStructs.h
+)
+SOURCE_GROUP( OpenGEX FILES ${OpenGEX_SRCS})
+
 SET( Ply_SRCS
 SET( Ply_SRCS
 	PlyLoader.cpp
 	PlyLoader.cpp
 	PlyLoader.h
 	PlyLoader.h
@@ -636,6 +641,17 @@ SET( unzip_SRCS
 )
 )
 SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 
 
+SET ( openddl_parser_SRCS
+    ../contrib/openddlparser/code/OpenDDLParser.cpp
+    ../contrib/openddlparser/code/DDLNode.cpp
+    ../contrib/openddlparser/code/Value.cpp
+    ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
+    ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
+    ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
+    ../contrib/openddlparser/include/openddlparser/DDLNode.h
+    ../contrib/openddlparser/include/openddlparser/Value.h
+)
+SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS})
 
 
 # VC2010 fixes
 # VC2010 fixes
 if(MSVC10)
 if(MSVC10)
@@ -691,6 +707,7 @@ SET( assimp_src
 	${OFFFormat_SRCS}
 	${OFFFormat_SRCS}
 	${Obj_SRCS}
 	${Obj_SRCS}
 	${Ogre_SRCS}
 	${Ogre_SRCS}
+    ${OpenGEX_SRCS}
 	${Ply_SRCS}
 	${Ply_SRCS}
 	${Q3D_SRCS}
 	${Q3D_SRCS}
 	${Q3BSP_SRCS}
 	${Q3BSP_SRCS}
@@ -715,6 +732,7 @@ SET( assimp_src
 	${unzip_compile_SRCS}
 	${unzip_compile_SRCS}
 	${Poly2Tri_SRCS}
 	${Poly2Tri_SRCS}
 	${Clipper_SRCS}
 	${Clipper_SRCS}
+    ${openddl_parser_SRCS}
 	# Necessary to show the headers in the project when using the VC++ generator:
 	# Necessary to show the headers in the project when using the VC++ generator:
 	${Boost_SRCS}
 	${Boost_SRCS}
 
 
@@ -722,6 +740,11 @@ SET( assimp_src
 	${COMPILER_HEADERS}
 	${COMPILER_HEADERS}
 
 
 )
 )
+add_definitions( -DOPENDDLPARSER_BUILD )
+
+INCLUDE_DIRECTORIES( 
+    ../contrib/openddlparser/include
+)
 
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 	SET( assimp_src ${assimp_src} ${C4D_SRCS})
 	SET( assimp_src ${assimp_src} ${C4D_SRCS})
@@ -730,7 +753,7 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 
 
 ADD_LIBRARY( assimp ${assimp_src} )
 ADD_LIBRARY( assimp ${assimp_src} )
 
 
-TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES})
+TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} )
 
 
 if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
 if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
 	set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
 	set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)

+ 6 - 2
code/COBLoader.cpp

@@ -154,13 +154,17 @@ void COBImporter::InternReadFile( const std::string& pFile,
 	}
 	}
 
 
 	DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
 	DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
-	void (COBImporter::* load)(Scene&,StreamReaderLE*)= head[15]=='A'?&COBImporter::ReadAsciiFile:&COBImporter::ReadBinaryFile;
 	if (head[16]!='L') {
 	if (head[16]!='L') {
 		ThrowException("File is big-endian, which is not supported");
 		ThrowException("File is big-endian, which is not supported");
 	}
 	}
 	
 	
 	// load data into intermediate structures
 	// load data into intermediate structures
-	(this->*load)(scene,stream.get());
+	if (head[15]=='A') {
+		ReadAsciiFile(scene, stream.get());
+	}
+	else {
+		ReadBinaryFile(scene, stream.get());
+	}
 	if(scene.nodes.empty()) {
 	if(scene.nodes.empty()) {
 		ThrowException("No nodes loaded");
 		ThrowException("No nodes loaded");
 	}
 	}

+ 1 - 1
code/ColladaExporter.cpp

@@ -65,7 +65,7 @@ namespace Assimp
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
-void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	std::string path = "";
 	std::string path = "";
 	std::string file = pFile;
 	std::string file = pFile;

+ 1 - 0
code/ColladaHelper.h

@@ -405,6 +405,7 @@ struct Controller
 /** A collada material. Pretty much the only member is a reference to an effect. */
 /** A collada material. Pretty much the only member is a reference to an effect. */
 struct Material
 struct Material
 {
 {
+	std::string mName;
 	std::string mEffect;
 	std::string mEffect;
 };
 };
 
 

+ 2 - 2
code/ColladaLoader.cpp

@@ -182,7 +182,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
 				 0,  0,  1,  0,
 				 0,  0,  1,  0,
 				 0, -1,  0,  0,
 				 0, -1,  0,  0,
 				 0,  0,  0,  1);
 				 0,  0,  0,  1);
-        }
+		}
 	// store all meshes
 	// store all meshes
 	StoreSceneMeshes( pScene);
 	StoreSceneMeshes( pScene);
 
 
@@ -1385,7 +1385,7 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 
 
 		// create material
 		// create material
 		aiMaterial* mat = new aiMaterial;
 		aiMaterial* mat = new aiMaterial;
-		aiString name( matIt->first);
+		aiString name( material.mName.empty() ? matIt->first : material.mName );
 		mat->AddProperty(&name,AI_MATKEY_NAME);
 		mat->AddProperty(&name,AI_MATKEY_NAME);
 
 
 		// store the material
 		// store the material

+ 41 - 7
code/ColladaParser.cpp

@@ -66,7 +66,7 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
 {
 {
 	mRootNode = NULL;
 	mRootNode = NULL;
 	mUnitSize = 1.0f;
 	mUnitSize = 1.0f;
-	mUpDirection = UP_Z;
+	mUpDirection = UP_Y;
 
 
 	// We assume the newest file format by default
 	// We assume the newest file format by default
 	mFormat = FV_1_5_n;
 	mFormat = FV_1_5_n;
@@ -231,10 +231,10 @@ void ColladaParser::ReadAssetInfo()
 				const char* content = GetTextContent();
 				const char* content = GetTextContent();
 				if( strncmp( content, "X_UP", 4) == 0)
 				if( strncmp( content, "X_UP", 4) == 0)
 					mUpDirection = UP_X;
 					mUpDirection = UP_X;
-				else if( strncmp( content, "Y_UP", 4) == 0)
-					mUpDirection = UP_Y;
-				else
+				else if( strncmp( content, "Z_UP", 4) == 0)
 					mUpDirection = UP_Z;
 					mUpDirection = UP_Z;
+				else
+					mUpDirection = UP_Y;
 
 
 				// check element end
 				// check element end
 				TestClosing( "up_axis");
 				TestClosing( "up_axis");
@@ -823,6 +823,7 @@ void ColladaParser::ReadMaterialLibrary()
 	if( mReader->isEmptyElement())
 	if( mReader->isEmptyElement())
 		return;
 		return;
 
 
+	std::map<std::string, int> names;
 	while( mReader->read())
 	while( mReader->read())
 	{
 	{
 		if( mReader->getNodeType() == irr::io::EXN_ELEMENT) 
 		if( mReader->getNodeType() == irr::io::EXN_ELEMENT) 
@@ -833,8 +834,32 @@ void ColladaParser::ReadMaterialLibrary()
 				int attrID = GetAttribute( "id");
 				int attrID = GetAttribute( "id");
 				std::string id = mReader->getAttributeValue( attrID);
 				std::string id = mReader->getAttributeValue( attrID);
 
 
+				std::string name;
+				int attrName = TestAttribute("name");
+				if (attrName >= 0)
+					name = mReader->getAttributeValue( attrName);
+
 				// create an entry and store it in the library under its ID
 				// create an entry and store it in the library under its ID
-				ReadMaterial(mMaterialLibrary[id] = Material());
+				mMaterialLibrary[id] = Material();
+
+				if( !name.empty())
+				{
+					std::map<std::string, int>::iterator it = names.find( name);
+					if( it != names.end())
+					{
+						std::ostringstream strStream;
+						strStream << ++it->second;
+						name.append( " " + strStream.str());
+					}
+					else
+					{
+						names[name] = 0;
+					}
+
+					mMaterialLibrary[id].mName = name;
+				}
+
+				ReadMaterial( mMaterialLibrary[id]);
 			} else
 			} else
 			{
 			{
 				// ignore the rest
 				// ignore the rest
@@ -1391,6 +1416,9 @@ void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler)
 				if( attrTex >= 0 )
 				if( attrTex >= 0 )
 	  				pSampler.mUVChannel = mReader->getAttributeValue( attrTex);
 	  				pSampler.mUVChannel = mReader->getAttributeValue( attrTex);
 				//SkipElement();
 				//SkipElement();
+
+				// as we've read texture, the color needs to be 1,1,1,1
+				pColor = aiColor4D(1.f, 1.f, 1.f, 1.f);
 			}
 			}
 			else if( IsElement( "technique"))
 			else if( IsElement( "technique"))
 			{
 			{
@@ -1942,6 +1970,10 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
 					// now here the actual fun starts - these are the indices to construct the mesh data from
 					// now here the actual fun starts - these are the indices to construct the mesh data from
 					actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType);
 					actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType);
 				}
 				}
+			}
+			else if (IsElement("extra"))
+			{
+				SkipElement("extra");
 			} else
 			} else
 			{
 			{
 				ThrowException( boost::str( boost::format( "Unexpected sub element <%s> in tag <%s>") % mReader->getNodeName() % elementName));
 				ThrowException( boost::str( boost::format( "Unexpected sub element <%s> in tag <%s>") % mReader->getNodeName() % elementName));
@@ -1956,9 +1988,11 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
 		}
 		}
 	}
 	}
 
 
-	// small sanity check
-	if (primType != Prim_TriFans && primType != Prim_TriStrips)
+#ifdef ASSIMP_BUILD_DEBUG  
+	if (primType != Prim_TriFans && primType != Prim_TriStrips) {
 		ai_assert(actualPrimitives == numPrimitives);
 		ai_assert(actualPrimitives == numPrimitives);
+	}
+#endif
 
 
 	// only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
 	// only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
 	subgroup.mNumFaces = actualPrimitives;
 	subgroup.mNumFaces = actualPrimitives;

+ 128 - 15
code/Exporter.cpp

@@ -78,16 +78,16 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
 // do not use const, because some exporter need to convert the scene temporary
 // do not use const, because some exporter need to convert the scene temporary
-void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
-void ExportSceneXFile(const char*,IOSystem*, const aiScene*); 
-void ExportSceneObj(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
-void ExportScenePly(const char*,IOSystem*, const aiScene*);
-void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*);
-void ExportScene3DS(const char*, IOSystem*, const aiScene*);
-void ExportSceneAssbin(const char*, IOSystem*, const aiScene*);
-void ExportSceneAssxml(const char*, IOSystem*, const aiScene*);
+void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*); 
+void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // global array of all export formats which Assimp supports in its current build
 // global array of all export formats which Assimp supports in its current build
@@ -97,7 +97,7 @@ Exporter::ExportFormatEntry gExporters[] =
 	Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
 	Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
 #endif
 #endif
 
 
-#ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER
+#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
 	Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
 	Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
 		aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
 		aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
 #endif
 #endif
@@ -232,7 +232,7 @@ bool Exporter :: IsDefaultIOHandler() const
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int )
+const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties)
 {
 {
 	if (pimpl->blob) {
 	if (pimpl->blob) {
 		delete pimpl->blob;
 		delete pimpl->blob;
@@ -288,7 +288,7 @@ bool IsVerboseFormat(const aiScene* pScene)
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
+aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
 {
 {
 	ASSIMP_BEGIN_EXCEPTION_REGION();
 	ASSIMP_BEGIN_EXCEPTION_REGION();
 
 
@@ -296,7 +296,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
 	// format. They will likely not be aware that there is a flag in the scene to indicate
 	// format. They will likely not be aware that there is a flag in the scene to indicate
 	// this, however. To avoid surprises and bug reports, we check for duplicates in
 	// this, however. To avoid surprises and bug reports, we check for duplicates in
 	// meshes upfront.
 	// meshes upfront.
-	const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
+	const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);	
 
 
 	pimpl->mError = "";
 	pimpl->mError = "";
 	for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
 	for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
@@ -403,7 +403,8 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
 					proc.Execute(scenecopy.get());
 					proc.Execute(scenecopy.get());
 				}
 				}
 
 
-				exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
+				ExportProperties emptyProperties;  // Never pass NULL ExportProperties so Exporters don't have to worry.
+				exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);
 			}
 			}
 			catch (DeadlyExportError& err) {
 			catch (DeadlyExportError& err) {
 				pimpl->mError = err.what();
 				pimpl->mError = err.what();
@@ -498,4 +499,116 @@ void Exporter :: UnregisterExporter(const char* id)
 	}
 	}
 }
 }
 
 
+ExportProperties :: ExportProperties() {}
+
+ExportProperties::ExportProperties(const ExportProperties &other)
+	 : mIntProperties(other.mIntProperties),
+   mFloatProperties(other.mFloatProperties),
+   mStringProperties(other.mStringProperties),
+   mMatrixProperties(other.mMatrixProperties)
+{
+	
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyInteger(const char* szName, int iValue, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<int>(mIntProperties, szName,iValue,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyFloat(const char* szName, float iValue, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<float>(mFloatProperties, szName,iValue,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyString(const char* szName, const std::string& value, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<std::string>(mStringProperties, szName,value,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyMatrix(const char* szName, const aiMatrix4x4& value, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<aiMatrix4x4>(mMatrixProperties, szName,value,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+int ExportProperties :: GetPropertyInteger(const char* szName, 
+	int iErrorReturn /*= 0xffffffff*/) const
+{
+	return GetGenericProperty<int>(mIntProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+float ExportProperties :: GetPropertyFloat(const char* szName, 
+	float iErrorReturn /*= 10e10*/) const
+{
+	return GetGenericProperty<float>(mFloatProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+const std::string ExportProperties :: GetPropertyString(const char* szName, 
+	const std::string& iErrorReturn /*= ""*/) const
+{
+	return GetGenericProperty<std::string>(mStringProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+const aiMatrix4x4 ExportProperties :: GetPropertyMatrix(const char* szName, 
+	const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
+{
+	return GetGenericProperty<aiMatrix4x4>(mMatrixProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyInteger(const char* szName) const
+{
+	return HasGenericProperty<int>(mIntProperties, szName);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyBool(const char* szName) const
+{
+	return HasGenericProperty<int>(mIntProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyFloat(const char* szName) const
+{
+	return HasGenericProperty<float>(mFloatProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyString(const char* szName) const
+{
+	return HasGenericProperty<std::string>(mStringProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyMatrix(const char* szName) const
+{
+	return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName);
+};
+
+
 #endif // !ASSIMP_BUILD_NO_EXPORT
 #endif // !ASSIMP_BUILD_NO_EXPORT

+ 124 - 34
code/FBXConverter.cpp

@@ -1971,9 +1971,12 @@ private:
 
 
 		// strip AnimationStack:: prefix
 		// strip AnimationStack:: prefix
 		std::string name = st.Name();
 		std::string name = st.Name();
-		if(name.substr(0,16) == "AnimationStack::") {
+		if (name.substr(0, 16) == "AnimationStack::") {
 			name = name.substr(16);
 			name = name.substr(16);
 		}
 		}
+		else if (name.substr(0, 11) == "AnimStack::") {
+			name = name.substr(11);
+		}
 
 
 		anim->mName.Set(name);
 		anim->mName.Set(name);
 		
 		
@@ -2017,12 +2020,18 @@ private:
 		double min_time = 1e10;
 		double min_time = 1e10;
 		double max_time = -1e10;
 		double max_time = -1e10;
 
 
+		int64_t start_time = st.LocalStart();
+		int64_t stop_time = st.LocalStop();
+		double start_timeF = CONVERT_FBX_TIME(start_time);
+		double stop_timeF = CONVERT_FBX_TIME(stop_time);
+
 		try {
 		try {
 			BOOST_FOREACH(const NodeMap::value_type& kv, node_map) {
 			BOOST_FOREACH(const NodeMap::value_type& kv, node_map) {
 				GenerateNodeAnimations(node_anims, 
 				GenerateNodeAnimations(node_anims, 
 					kv.first, 
 					kv.first, 
 					kv.second, 
 					kv.second, 
 					layer_map, 
 					layer_map, 
+					start_time, stop_time,
 					max_time, 
 					max_time, 
 					min_time);
 					min_time);
 			}
 			}
@@ -2046,9 +2055,27 @@ private:
 			return;
 			return;
 		}
 		}
 
 
+		//adjust relative timing for animation
+		{
+			double start_fps = start_timeF * anim_fps;
+
+			for (unsigned int c = 0; c < anim->mNumChannels; c++)
+			{
+				aiNodeAnim* channel = anim->mChannels[c];
+				for (uint32_t i = 0; i < channel->mNumPositionKeys; i++)
+					channel->mPositionKeys[i].mTime -= start_fps;
+				for (uint32_t i = 0; i < channel->mNumRotationKeys; i++)
+					channel->mRotationKeys[i].mTime -= start_fps;
+				for (uint32_t i = 0; i < channel->mNumScalingKeys; i++)
+					channel->mScalingKeys[i].mTime -= start_fps;
+			}
+
+			max_time -= min_time;
+		}
+
 		// for some mysterious reason, mDuration is simply the maximum key -- the
 		// for some mysterious reason, mDuration is simply the maximum key -- the
 		// validator always assumes animations to start at zero.
 		// validator always assumes animations to start at zero.
-		anim->mDuration = max_time /*- min_time */;
+		anim->mDuration = (stop_timeF - start_timeF) * anim_fps;
 		anim->mTicksPerSecond = anim_fps;
 		anim->mTicksPerSecond = anim_fps;
 	}
 	}
 
 
@@ -2058,6 +2085,7 @@ private:
 		const std::string& fixed_name, 
 		const std::string& fixed_name, 
 		const std::vector<const AnimationCurveNode*>& curves, 
 		const std::vector<const AnimationCurveNode*>& curves, 
 		const LayerMap& layer_map, 
 		const LayerMap& layer_map, 
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& max_time,
 		double& min_time)
 		double& min_time)
 	{
 	{
@@ -2150,13 +2178,19 @@ private:
 			aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain, 
 			aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain, 
 				node_property_map.end(), 
 				node_property_map.end(), 
 				layer_map,
 				layer_map,
+				start, stop,
 				max_time,
 				max_time,
 				min_time,
 				min_time,
 				true // input is TRS order, assimp is SRT
 				true // input is TRS order, assimp is SRT
 				);
 				);
 
 
 			ai_assert(nd);
 			ai_assert(nd);
-			node_anims.push_back(nd);
+			if (nd->mNumPositionKeys == 0 && nd->mNumRotationKeys == 0 && nd->mNumScalingKeys == 0) {
+				delete nd;
+			}
+			else {
+				node_anims.push_back(nd);
+			}
 			return;
 			return;
 		}
 		}
 
 
@@ -2188,6 +2222,7 @@ private:
 						target, 
 						target, 
 						(*chain[i]).second,
 						(*chain[i]).second,
 						layer_map,
 						layer_map,
+						start, stop,
 						max_time,
 						max_time,
 						min_time);
 						min_time);
 
 
@@ -2203,6 +2238,7 @@ private:
 						target, 
 						target, 
 						(*chain[i]).second,
 						(*chain[i]).second,
 						layer_map,
 						layer_map,
+						start, stop,
 						max_time,
 						max_time,
 						min_time);
 						min_time);
 
 
@@ -2215,12 +2251,18 @@ private:
 							target, 
 							target, 
 							(*chain[i]).second,
 							(*chain[i]).second,
 							layer_map,
 							layer_map,
+							start, stop,
 							max_time,
 							max_time,
 							min_time,
 							min_time,
 							true);
 							true);
 
 
 						ai_assert(inv);
 						ai_assert(inv);
-						node_anims.push_back(inv);
+						if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) {
+							delete inv;
+						}
+						else {
+							node_anims.push_back(inv);
+						}
 
 
 						ai_assert(TransformationComp_RotationPivotInverse > i);
 						ai_assert(TransformationComp_RotationPivotInverse > i);
 						flags |= bit << (TransformationComp_RotationPivotInverse - i);
 						flags |= bit << (TransformationComp_RotationPivotInverse - i);
@@ -2233,12 +2275,18 @@ private:
 							target, 
 							target, 
 							(*chain[i]).second,
 							(*chain[i]).second,
 							layer_map,
 							layer_map,
+							start, stop,
 							max_time,
 							max_time,
 							min_time,
 							min_time,
 							true);
 							true);
 
 
 						ai_assert(inv);
 						ai_assert(inv);
-						node_anims.push_back(inv);
+						if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) {
+							delete inv;
+						}
+						else {
+							node_anims.push_back(inv);
+						}
 					
 					
 						ai_assert(TransformationComp_RotationPivotInverse > i);
 						ai_assert(TransformationComp_RotationPivotInverse > i);
 						flags |= bit << (TransformationComp_RotationPivotInverse - i);
 						flags |= bit << (TransformationComp_RotationPivotInverse - i);
@@ -2252,6 +2300,7 @@ private:
 						target, 
 						target, 
 						(*chain[i]).second,
 						(*chain[i]).second,
 						layer_map,
 						layer_map,
+						start, stop,
 						max_time,
 						max_time,
 						min_time);
 						min_time);
 
 
@@ -2262,7 +2311,12 @@ private:
 				}
 				}
 
 
 				ai_assert(na);
 				ai_assert(na);
-				node_anims.push_back(na);
+				if (na->mNumPositionKeys == 0 && na->mNumRotationKeys == 0 && na->mNumScalingKeys == 0) {
+					delete na;
+				}
+				else {
+					node_anims.push_back(na);
+				}
 				continue;
 				continue;
 			}
 			}
 		}
 		}
@@ -2323,13 +2377,14 @@ private:
 		const Model& target, 
 		const Model& target, 
 		const std::vector<const AnimationCurveNode*>& curves,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& max_time,
 		double& min_time)
 		double& min_time)
 	{
 	{
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		na->mNodeName.Set(name);
 		na->mNodeName.Set(name);
 
 
-		ConvertRotationKeys(na, curves, layer_map, max_time,min_time, target.RotationOrder());
+		ConvertRotationKeys(na, curves, layer_map, start, stop, max_time, min_time, target.RotationOrder());
 
 
 		// dummy scaling key
 		// dummy scaling key
 		na->mScalingKeys = new aiVectorKey[1];
 		na->mScalingKeys = new aiVectorKey[1];
@@ -2354,13 +2409,14 @@ private:
 		const Model& /*target*/,
 		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& max_time,
 		double& min_time)
 		double& min_time)
 	{
 	{
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		na->mNodeName.Set(name);
 		na->mNodeName.Set(name);
 
 
-		ConvertScaleKeys(na, curves, layer_map, max_time,min_time);
+		ConvertScaleKeys(na, curves, layer_map, start, stop, max_time, min_time);
 
 
 		// dummy rotation key
 		// dummy rotation key
 		na->mRotationKeys = new aiQuatKey[1];
 		na->mRotationKeys = new aiQuatKey[1];
@@ -2385,6 +2441,7 @@ private:
 		const Model& /*target*/,
 		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& max_time,
 		double& min_time,
 		double& min_time,
 		bool inverse = false)
 		bool inverse = false)
@@ -2392,7 +2449,7 @@ private:
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		na->mNodeName.Set(name);
 		na->mNodeName.Set(name);
 
 
-		ConvertTranslationKeys(na, curves, layer_map, max_time,min_time);
+		ConvertTranslationKeys(na, curves, layer_map, start, stop, max_time, min_time);
 
 
 		if (inverse) {
 		if (inverse) {
 			for (unsigned int i = 0; i < na->mNumPositionKeys; ++i) {
 			for (unsigned int i = 0; i < na->mNumPositionKeys; ++i) {
@@ -2425,6 +2482,7 @@ private:
 		NodeMap::const_iterator chain[TransformationComp_MAXIMUM], 
 		NodeMap::const_iterator chain[TransformationComp_MAXIMUM], 
 		NodeMap::const_iterator iter_end,
 		NodeMap::const_iterator iter_end,
 		const LayerMap& layer_map,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& max_time,
 		double& min_time,
 		double& min_time,
 		bool reverse_order = false)
 		bool reverse_order = false)
@@ -2446,21 +2504,21 @@ private:
 			KeyFrameListList rotation;
 			KeyFrameListList rotation;
 			
 			
 			if(chain[TransformationComp_Scaling] != iter_end) {
 			if(chain[TransformationComp_Scaling] != iter_end) {
-				scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second);
+				scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop);
 			}
 			}
 			else {
 			else {
 				def_scale = PropertyGet(props,"Lcl Scaling",aiVector3D(1.f,1.f,1.f));
 				def_scale = PropertyGet(props,"Lcl Scaling",aiVector3D(1.f,1.f,1.f));
 			}
 			}
 
 
 			if(chain[TransformationComp_Translation] != iter_end) {
 			if(chain[TransformationComp_Translation] != iter_end) {
-				translation = GetKeyframeList((*chain[TransformationComp_Translation]).second);
+				translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop);
 			}
 			}
 			else {
 			else {
 				def_translate = PropertyGet(props,"Lcl Translation",aiVector3D(0.f,0.f,0.f));
 				def_translate = PropertyGet(props,"Lcl Translation",aiVector3D(0.f,0.f,0.f));
 			}
 			}
 			
 			
 			if(chain[TransformationComp_Rotation] != iter_end) {
 			if(chain[TransformationComp_Rotation] != iter_end) {
-				rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second);
+				rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop);
 			}
 			}
 			else {
 			else {
 				def_rot = EulerToQuaternion(PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)),
 				def_rot = EulerToQuaternion(PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)),
@@ -2478,17 +2536,20 @@ private:
 			aiVectorKey* out_scale = new aiVectorKey[times.size()];
 			aiVectorKey* out_scale = new aiVectorKey[times.size()];
 			aiVectorKey* out_translation = new aiVectorKey[times.size()];
 			aiVectorKey* out_translation = new aiVectorKey[times.size()];
 
 
-			ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation, 
-				scaling, 
-				translation, 
-				rotation, 
-				times,
-				max_time,
-				min_time,
-				target.RotationOrder(),
-				def_scale,
-				def_translate,
-				def_rot);
+			if (times.size())
+			{
+				ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation,
+					scaling,
+					translation,
+					rotation,
+					times,
+					max_time,
+					min_time,
+					target.RotationOrder(),
+					def_scale,
+					def_translate,
+					def_rot);
+			}
 
 
 			// XXX remove duplicates / redundant keys which this operation did
 			// XXX remove duplicates / redundant keys which this operation did
 			// likely produce if not all three channels were equally dense.
 			// likely produce if not all three channels were equally dense.
@@ -2510,6 +2571,7 @@ private:
 			if(chain[TransformationComp_Scaling] != iter_end) {
 			if(chain[TransformationComp_Scaling] != iter_end) {
 				ConvertScaleKeys(na, (*chain[TransformationComp_Scaling]).second, 
 				ConvertScaleKeys(na, (*chain[TransformationComp_Scaling]).second, 
 					layer_map, 
 					layer_map, 
+					start, stop,
 					max_time, 
 					max_time, 
 					min_time);
 					min_time);
 			}
 			}
@@ -2525,6 +2587,7 @@ private:
 			if(chain[TransformationComp_Rotation] != iter_end) {
 			if(chain[TransformationComp_Rotation] != iter_end) {
 				ConvertRotationKeys(na, (*chain[TransformationComp_Rotation]).second, 
 				ConvertRotationKeys(na, (*chain[TransformationComp_Rotation]).second, 
 					layer_map, 
 					layer_map, 
+					start, stop,
 					max_time,
 					max_time,
 					min_time,
 					min_time,
 					target.RotationOrder());
 					target.RotationOrder());
@@ -2542,6 +2605,7 @@ private:
 			if(chain[TransformationComp_Translation] != iter_end) {
 			if(chain[TransformationComp_Translation] != iter_end) {
 				ConvertTranslationKeys(na, (*chain[TransformationComp_Translation]).second, 
 				ConvertTranslationKeys(na, (*chain[TransformationComp_Translation]).second, 
 					layer_map, 
 					layer_map, 
+					start, stop,
 					max_time, 
 					max_time, 
 					min_time);
 					min_time);
 			}
 			}
@@ -2561,17 +2625,21 @@ private:
 
 
 
 
 	// key (time), value, mapto (component index)
 	// key (time), value, mapto (component index)
-	typedef boost::tuple< const KeyTimeList*, const KeyValueList*, unsigned int > KeyFrameList;
+	typedef boost::tuple<boost::shared_ptr<KeyTimeList>, boost::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
 	typedef std::vector<KeyFrameList> KeyFrameListList;
 	typedef std::vector<KeyFrameList> KeyFrameListList;
 
 
 	
 	
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
-	KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes)
+	KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop)
 	{
 	{
 		KeyFrameListList inputs;
 		KeyFrameListList inputs;
 		inputs.reserve(nodes.size()*3);
 		inputs.reserve(nodes.size()*3);
 
 
+		//give some breathing room for rounding errors
+		int64_t adj_start = start - 10000;
+		int64_t adj_stop = stop + 10000;
+
 		BOOST_FOREACH(const AnimationCurveNode* node, nodes) {
 		BOOST_FOREACH(const AnimationCurveNode* node, nodes) {
 			ai_assert(node);
 			ai_assert(node);
 
 
@@ -2596,7 +2664,23 @@ private:
 				const AnimationCurve* const curve = kv.second;
 				const AnimationCurve* const curve = kv.second;
 				ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size());
 				ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size());
 
 
-				inputs.push_back(boost::make_tuple(&curve->GetKeys(), &curve->GetValues(), mapto));
+				//get values within the start/stop time window
+				boost::shared_ptr<KeyTimeList> Keys(new KeyTimeList());
+				boost::shared_ptr<KeyValueList> Values(new KeyValueList());
+				const int count = curve->GetKeys().size();
+				Keys->reserve(count);
+				Values->reserve(count);
+				for (int n = 0; n < count; n++)
+				{
+					int64_t k = curve->GetKeys().at(n);
+					if (k >= adj_start && k <= adj_stop)
+					{
+						Keys->push_back(k);
+						Values->push_back(curve->GetValues().at(n));
+					}
+				}
+
+				inputs.push_back(boost::make_tuple(Keys, Values, mapto));
 			}
 			}
 		}
 		}
 		return inputs; // pray for NRVO :-)
 		return inputs; // pray for NRVO :-)
@@ -2626,7 +2710,7 @@ private:
 		const size_t count = inputs.size();
 		const size_t count = inputs.size();
 		while(true) {
 		while(true) {
 
 
-			uint64_t min_tick = std::numeric_limits<uint64_t>::max();
+			int64_t min_tick = std::numeric_limits<int64_t>::max();
 			for (size_t i = 0; i < count; ++i) {
 			for (size_t i = 0; i < count; ++i) {
 				const KeyFrameList& kfl = inputs[i];
 				const KeyFrameList& kfl = inputs[i];
 
 
@@ -2635,7 +2719,7 @@ private:
 				}
 				}
 			}
 			}
 
 
-			if (min_tick == std::numeric_limits<uint64_t>::max()) {
+			if (min_tick == std::numeric_limits<int64_t>::max()) {
 				break;
 				break;
 			}
 			}
 			keys.push_back(min_tick);
 			keys.push_back(min_tick);
@@ -2835,6 +2919,7 @@ private:
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
 	void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
+		int64_t start, int64_t stop,
 		double& maxTime,
 		double& maxTime,
 		double& minTime)
 		double& minTime)
 	{
 	{
@@ -2844,36 +2929,40 @@ private:
 		// layers should be multiplied with each other). There is a FBX 
 		// layers should be multiplied with each other). There is a FBX 
 		// property in the layer to specify the behaviour, though.
 		// property in the layer to specify the behaviour, though.
 
 
-		const KeyFrameListList& inputs = GetKeyframeList(nodes);
+		const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop);
 		const KeyTimeList& keys = GetKeyTimeList(inputs);
 		const KeyTimeList& keys = GetKeyTimeList(inputs);
 
 
 		na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
 		na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
 		na->mScalingKeys = new aiVectorKey[keys.size()];
 		na->mScalingKeys = new aiVectorKey[keys.size()];
-		InterpolateKeys(na->mScalingKeys, keys, inputs, true, maxTime, minTime);
+		if (keys.size() > 0)
+			InterpolateKeys(na->mScalingKeys, keys, inputs, true, maxTime, minTime);
 	}
 	}
 
 
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
 	void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
 		const LayerMap& /*layers*/,
 		const LayerMap& /*layers*/,
+		int64_t start, int64_t stop,
 		double& maxTime,
 		double& maxTime,
 		double& minTime)
 		double& minTime)
 	{
 	{
 		ai_assert(nodes.size());
 		ai_assert(nodes.size());
 
 
 		// XXX see notes in ConvertScaleKeys()
 		// XXX see notes in ConvertScaleKeys()
-		const KeyFrameListList& inputs = GetKeyframeList(nodes);
+		const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop);
 		const KeyTimeList& keys = GetKeyTimeList(inputs);
 		const KeyTimeList& keys = GetKeyTimeList(inputs);
 
 
 		na->mNumPositionKeys = static_cast<unsigned int>(keys.size());
 		na->mNumPositionKeys = static_cast<unsigned int>(keys.size());
 		na->mPositionKeys = new aiVectorKey[keys.size()];
 		na->mPositionKeys = new aiVectorKey[keys.size()];
-		InterpolateKeys(na->mPositionKeys, keys, inputs, false, maxTime, minTime);
+		if (keys.size() > 0)
+			InterpolateKeys(na->mPositionKeys, keys, inputs, false, maxTime, minTime);
 	}
 	}
 
 
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
 	void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
 		const LayerMap& /*layers*/,
 		const LayerMap& /*layers*/,
+		int64_t start, int64_t stop,
 		double& maxTime,
 		double& maxTime,
 		double& minTime,
 		double& minTime,
 		Model::RotOrder order)
 		Model::RotOrder order)
@@ -2881,12 +2970,13 @@ private:
 		ai_assert(nodes.size());
 		ai_assert(nodes.size());
 
 
 		// XXX see notes in ConvertScaleKeys()
 		// XXX see notes in ConvertScaleKeys()
-		const std::vector< KeyFrameList >& inputs = GetKeyframeList(nodes);
+		const std::vector< KeyFrameList >& inputs = GetKeyframeList(nodes, start, stop);
 		const KeyTimeList& keys = GetKeyTimeList(inputs);
 		const KeyTimeList& keys = GetKeyTimeList(inputs);
 
 
 		na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
 		na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
 		na->mRotationKeys = new aiQuatKey[keys.size()];
 		na->mRotationKeys = new aiQuatKey[keys.size()];
-		InterpolateKeys(na->mRotationKeys, keys, inputs, false, maxTime, minTime, order);
+		if (keys.size() > 0)
+			InterpolateKeys(na->mRotationKeys, keys, inputs, false, maxTime, minTime, order);
 	}
 	}
 
 
 
 

+ 5 - 5
code/FBXDocument.h

@@ -882,7 +882,7 @@ private:
 	std::vector<unsigned int> mappings;
 	std::vector<unsigned int> mappings;
 };
 };
 
 
-typedef std::vector<uint64_t> KeyTimeList;
+typedef std::vector<int64_t> KeyTimeList;
 typedef std::vector<float> KeyValueList;
 typedef std::vector<float> KeyValueList;
 
 
 /** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
 /** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
@@ -1026,10 +1026,10 @@ public:
 
 
 public:
 public:
 
 
-	fbx_simple_property(LocalStart, uint64_t, 0L)
-	fbx_simple_property(LocalStop, uint64_t, 0L)
-	fbx_simple_property(ReferenceStart, uint64_t, 0L)
-	fbx_simple_property(ReferenceStop, uint64_t, 0L)
+	fbx_simple_property(LocalStart, int64_t, 0L)
+	fbx_simple_property(LocalStop, int64_t, 0L)
+	fbx_simple_property(ReferenceStart, int64_t, 0L)
+	fbx_simple_property(ReferenceStop, int64_t, 0L)
 
 
 
 
 
 

+ 106 - 0
code/FBXParser.cpp

@@ -432,6 +432,43 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
 }
 }
 
 
 
 
+// ------------------------------------------------------------------------------------------------
+int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
+{
+	err_out = NULL;
+
+	if (t.Type() != TokenType_DATA) {
+		err_out = "expected TOK_DATA token";
+		return 0L;
+	}
+
+	if (t.IsBinary())
+	{
+		const char* data = t.begin();
+		if (data[0] != 'L') {
+			err_out = "failed to parse Int64, unexpected data type";
+			return 0L;
+		}
+
+		BE_NCONST int64_t id = SafeParse<int64_t>(data + 1, t.end());
+		AI_SWAP8(id);
+		return id;
+	}
+
+	// XXX: should use size_t here
+	unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
+	ai_assert(length > 0);
+
+	const char* out;
+	const int64_t id = strtol10_64(t.begin(), &out, &length);
+	if (out > t.end()) {
+		err_out = "failed to parse Int64 (text)";
+		return 0L;
+	}
+
+	return id;
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 std::string ParseTokenAsString(const Token& t, const char*& err_out)
 std::string ParseTokenAsString(const Token& t, const char*& err_out)
 {
 {
@@ -1063,6 +1100,63 @@ void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
 	}
 	}
 }
 }
 
 
+// ------------------------------------------------------------------------------------------------
+// read an array of int64_ts
+void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
+{
+	out.clear();
+	const TokenList& tok = el.Tokens();
+	if (tok.empty()) {
+		ParseError("unexpected empty element", &el);
+	}
+
+	if (tok[0]->IsBinary()) {
+		const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+		char type;
+		uint32_t count;
+		ReadBinaryDataArrayHead(data, end, type, count, el);
+
+		if (!count) {
+			return;
+		}
+
+		if (type != 'l') {
+			ParseError("expected long array (binary)", &el);
+		}
+
+		std::vector<char> buff;
+		ReadBinaryDataArray(type, count, data, end, buff, el);
+
+		ai_assert(data == end);
+		ai_assert(buff.size() == count * 8);
+
+		out.reserve(count);
+
+		const int64_t* ip = reinterpret_cast<const int64_t*>(&buff[0]);
+		for (unsigned int i = 0; i < count; ++i, ++ip) {
+			BE_NCONST int64_t val = *ip;
+			AI_SWAP8(val);
+			out.push_back(val);
+		}
+
+		return;
+	}
+
+	const size_t dim = ParseTokenAsDim(*tok[0]);
+
+	// see notes in ParseVectorDataArray()
+	out.reserve(dim);
+
+	const Scope& scope = GetRequiredScope(el);
+	const Element& a = GetRequiredElement(scope, "a", &el);
+
+	for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end;) {
+		const int64_t ival = ParseTokenAsInt64(**it++);
+
+		out.push_back(ival);
+	}
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 aiMatrix4x4 ReadMatrix(const Element& element)
 aiMatrix4x4 ReadMatrix(const Element& element)
@@ -1206,6 +1300,18 @@ int ParseTokenAsInt(const Token& t)
 
 
 
 
 
 
+// ------------------------------------------------------------------------------------------------
+// wrapper around ParseTokenAsInt64() with ParseError handling
+int64_t ParseTokenAsInt64(const Token& t)
+{
+	const char* err;
+	const int64_t i = ParseTokenAsInt64(t, err);
+	if (err) {
+		ParseError(err, t);
+	}
+	return i;
+}
+
 } // !FBX
 } // !FBX
 } // !Assimp
 } // !Assimp
 
 

+ 3 - 0
code/FBXParser.h

@@ -207,6 +207,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out);
 
 
 float ParseTokenAsFloat(const Token& t, const char*& err_out);
 float ParseTokenAsFloat(const Token& t, const char*& err_out);
 int ParseTokenAsInt(const Token& t, const char*& err_out);
 int ParseTokenAsInt(const Token& t, const char*& err_out);
+int64_t ParseTokenAsInt64(const Token& t, const char*& err_out);
 std::string ParseTokenAsString(const Token& t, const char*& err_out);
 std::string ParseTokenAsString(const Token& t, const char*& err_out);
 
 
 
 
@@ -215,6 +216,7 @@ uint64_t ParseTokenAsID(const Token& t);
 size_t ParseTokenAsDim(const Token& t);
 size_t ParseTokenAsDim(const Token& t);
 float ParseTokenAsFloat(const Token& t);
 float ParseTokenAsFloat(const Token& t);
 int ParseTokenAsInt(const Token& t);
 int ParseTokenAsInt(const Token& t);
+int64_t ParseTokenAsInt64(const Token& t);
 std::string ParseTokenAsString(const Token& t);
 std::string ParseTokenAsString(const Token& t);
 
 
 /* read data arrays */
 /* read data arrays */
@@ -225,6 +227,7 @@ void ParseVectorDataArray(std::vector<int>& out, const Element& el);
 void ParseVectorDataArray(std::vector<float>& out, const Element& el);
 void ParseVectorDataArray(std::vector<float>& out, const Element& el);
 void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el);
 void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el);
 void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e);
 void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e);
+void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
 
 
 
 
 
 

+ 5 - 2
code/FBXProperties.cpp

@@ -88,9 +88,12 @@ Property* ReadTypedProperty(const Element& element)
 	else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) {
 	else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) {
 		return new TypedProperty<int>(ParseTokenAsInt(*tok[4]));
 		return new TypedProperty<int>(ParseTokenAsInt(*tok[4]));
 	}
 	}
-	else if (!strcmp(cs,"ULongLong")) {
+	else if (!strcmp(cs, "ULongLong")) {
 		return new TypedProperty<uint64_t>(ParseTokenAsID(*tok[4]));
 		return new TypedProperty<uint64_t>(ParseTokenAsID(*tok[4]));
 	}
 	}
+	else if (!strcmp(cs, "KTime")) {
+		return new TypedProperty<int64_t>(ParseTokenAsInt64(*tok[4]));
+	}
 	else if (!strcmp(cs,"Vector3D") || 
 	else if (!strcmp(cs,"Vector3D") || 
 		!strcmp(cs,"ColorRGB") || 
 		!strcmp(cs,"ColorRGB") || 
 		!strcmp(cs,"Vector") || 
 		!strcmp(cs,"Vector") || 
@@ -105,7 +108,7 @@ Property* ReadTypedProperty(const Element& element)
 			ParseTokenAsFloat(*tok[6]))
 			ParseTokenAsFloat(*tok[6]))
 		);
 		);
 	}
 	}
-	else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"KTime") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView")) {
+	else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView")) {
 		return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
 		return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
 	}
 	}
 	return NULL;
 	return NULL;

+ 13 - 0
code/GenericProperty.h

@@ -111,5 +111,18 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
 		*bWasExisting = true;
 		*bWasExisting = true;
 }
 }
 
 
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline const bool HasGenericProperty(const std::map< unsigned int, T >& list, 
+	const char* szName)
+{
+	ai_assert(NULL != szName);
+	const uint32_t hash = SuperFastHash(szName);
+
+	typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
+	if (it == list.end()) return false;
+	
+	return true;
+}
 
 
 #endif // !! AI_GENERIC_PROPERTY_H_INCLUDED
 #endif // !! AI_GENERIC_PROPERTY_H_INCLUDED

+ 2 - 2
code/IFCCurve.cpp

@@ -648,10 +648,10 @@ void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
 	ai_assert(InRange(a) && InRange(b));
 	ai_assert(InRange(a) && InRange(b));
 
 
 	const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
 	const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
-	out.verts.reserve( out.verts.size() + cnt );
+	out.verts.reserve( out.verts.size() + cnt + 1);
 
 
 	IfcFloat p = a, delta = (b-a)/cnt;
 	IfcFloat p = a, delta = (b-a)/cnt;
-	for(size_t i = 0; i < cnt; ++i, p += delta) {
+	for(size_t i = 0; i <= cnt; ++i, p += delta) {
 		out.verts.push_back(Eval(p));
 		out.verts.push_back(Eval(p));
 	}
 	}
 }
 }

+ 95 - 76
code/IFCGeometry.cpp

@@ -523,43 +523,23 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
 	return m;
 	return m;
 }
 }
 
 
-
-// ------------------------------------------------------------------------------------------------
-void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result, 
-	ConversionData& conv, bool collect_openings)
+// Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary.
+void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curve,
+	const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings)
 {
 {
-	TempMesh meshout;
-	
-	// First read the profile description
-	if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
-		return;
-	}
-
-	IfcVector3 dir;
-	ConvertDirection(dir,solid.ExtrudedDirection);
-
-	dir *= solid.Depth; /*
-	if(conv.collect_openings && !conv.apply_openings) {
-		dir *= 1000.0;
-	} */
-
-	// Outline: assuming that `meshout.verts` is now a list of vertex points forming 
-	// the underlying profile, extrude along the given axis, forming new
-	// triangles.
-	
-	std::vector<IfcVector3>& in = meshout.verts;
-	const size_t size=in.size();
-
-	const bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
-	if(solid.Depth < 1e-6) {
-		if(has_area) {
-			result = meshout;
+	// Outline: 'curve' is now a list of vertex points forming the underlying profile, extrude along the given axis, 
+	// forming new triangles.
+	const bool has_area = solid.SweptArea->ProfileType == "AREA" && curve.verts.size() > 2;
+	if( solid.Depth < 1e-6 ) {
+		if( has_area ) {
+			result.Append(curve);
 		}
 		}
 		return;
 		return;
 	}
 	}
 
 
-	result.verts.reserve(size*(has_area?4:2));
-	result.vertcnt.reserve(meshout.vertcnt.size()+2);
+	result.verts.reserve(curve.verts.size()*(has_area ? 4 : 2));
+	result.vertcnt.reserve(curve.verts.size() + 2);
+	std::vector<IfcVector3> in = curve.verts;
 
 
 	// First step: transform all vertices into the target coordinate space
 	// First step: transform all vertices into the target coordinate space
 	IfcMatrix4 trafo;
 	IfcMatrix4 trafo;
@@ -567,7 +547,7 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
 
 
 	IfcVector3 vmin, vmax;
 	IfcVector3 vmin, vmax;
 	MinMaxChooser<IfcVector3>()(vmin, vmax);
 	MinMaxChooser<IfcVector3>()(vmin, vmax);
-	BOOST_FOREACH(IfcVector3& v,in) {
+	BOOST_FOREACH(IfcVector3& v, in) {
 		v *= trafo;
 		v *= trafo;
 
 
 		vmin = std::min(vmin, v);
 		vmin = std::min(vmin, v);
@@ -576,93 +556,91 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
 
 
 	vmax -= vmin;
 	vmax -= vmin;
 	const IfcFloat diag = vmax.Length();
 	const IfcFloat diag = vmax.Length();
-	
-	IfcVector3 min = in[0];
-	dir *= IfcMatrix3(trafo);
+	IfcVector3 dir = IfcMatrix3(trafo) * extrusionDir;
 
 
 	// reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction
 	// reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction
-	IfcVector3 profileNormal = TempMesh::ComputePolygonNormal( in.data(), in.size());
+	IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(in.data(), in.size());
 	if( profileNormal * dir < 0.0 )
 	if( profileNormal * dir < 0.0 )
-		std::reverse( in.begin(), in.end());
+		std::reverse(in.begin(), in.end());
 
 
 	std::vector<IfcVector3> nors;
 	std::vector<IfcVector3> nors;
 	const bool openings = !!conv.apply_openings && conv.apply_openings->size();
 	const bool openings = !!conv.apply_openings && conv.apply_openings->size();
-	
+
 	// Compute the normal vectors for all opening polygons as a prerequisite
 	// Compute the normal vectors for all opening polygons as a prerequisite
 	// to TryAddOpenings_Poly2Tri()
 	// to TryAddOpenings_Poly2Tri()
 	// XXX this belongs into the aforementioned function
 	// XXX this belongs into the aforementioned function
-	if (openings) {
+	if( openings ) {
 
 
-		if (!conv.settings.useCustomTriangulation) {	         
+		if( !conv.settings.useCustomTriangulation ) {
 			// it is essential to apply the openings in the correct spatial order. The direction	 
 			// it is essential to apply the openings in the correct spatial order. The direction	 
 			// doesn't matter, but we would screw up if we started with e.g. a door in between	 
 			// doesn't matter, but we would screw up if we started with e.g. a door in between	 
 			// two windows.	 
 			// two windows.	 
-			std::sort(conv.apply_openings->begin(),conv.apply_openings->end(),
-				TempOpening::DistanceSorter(min));	 
+			std::sort(conv.apply_openings->begin(), conv.apply_openings->end(), TempOpening::DistanceSorter(in[0]));
 		}
 		}
-	
+
 		nors.reserve(conv.apply_openings->size());
 		nors.reserve(conv.apply_openings->size());
-		BOOST_FOREACH(TempOpening& t,*conv.apply_openings) {
+		BOOST_FOREACH(TempOpening& t, *conv.apply_openings) {
 			TempMesh& bounds = *t.profileMesh.get();
 			TempMesh& bounds = *t.profileMesh.get();
-		
-			if (bounds.verts.size() <= 2) {
+
+			if( bounds.verts.size() <= 2 ) {
 				nors.push_back(IfcVector3());
 				nors.push_back(IfcVector3());
 				continue;
 				continue;
 			}
 			}
-			nors.push_back(((bounds.verts[2]-bounds.verts[0])^(bounds.verts[1]-bounds.verts[0]) ).Normalize());
+			nors.push_back(((bounds.verts[2] - bounds.verts[0]) ^ (bounds.verts[1] - bounds.verts[0])).Normalize());
 		}
 		}
 	}
 	}
-	
+
 
 
 	TempMesh temp;
 	TempMesh temp;
 	TempMesh& curmesh = openings ? temp : result;
 	TempMesh& curmesh = openings ? temp : result;
 	std::vector<IfcVector3>& out = curmesh.verts;
 	std::vector<IfcVector3>& out = curmesh.verts;
- 
+
 	size_t sides_with_openings = 0;
 	size_t sides_with_openings = 0;
-	for(size_t i = 0; i < size; ++i) {
-		const size_t next = (i+1)%size;
+	for( size_t i = 0; i < in.size(); ++i ) {
+		const size_t next = (i + 1) % in.size();
 
 
 		curmesh.vertcnt.push_back(4);
 		curmesh.vertcnt.push_back(4);
-		
+
 		out.push_back(in[i]);
 		out.push_back(in[i]);
 		out.push_back(in[next]);
 		out.push_back(in[next]);
-		out.push_back(in[next]+dir);
-		out.push_back(in[i]+dir);
+		out.push_back(in[next] + dir);
+		out.push_back(in[i] + dir);
 
 
-		if(openings) {
-			if((in[i]-in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings,nors,temp,true, true, dir)) {
+		if( openings ) {
+			if( (in[i] - in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
 				++sides_with_openings;
 				++sides_with_openings;
 			}
 			}
-			
+
 			result.Append(temp);
 			result.Append(temp);
 			temp.Clear();
 			temp.Clear();
 		}
 		}
 	}
 	}
 
 
-	if(openings) {
+	if( openings ) {
 		BOOST_FOREACH(TempOpening& opening, *conv.apply_openings) {
 		BOOST_FOREACH(TempOpening& opening, *conv.apply_openings) {
-			if (!opening.wallPoints.empty()) {
+			if( !opening.wallPoints.empty() ) {
 				IFCImporter::LogError("failed to generate all window caps");
 				IFCImporter::LogError("failed to generate all window caps");
 			}
 			}
 			opening.wallPoints.clear();
 			opening.wallPoints.clear();
 		}
 		}
 	}
 	}
-	
+
 	size_t sides_with_v_openings = 0;
 	size_t sides_with_v_openings = 0;
-	if(has_area) {
+	if( has_area ) {
 
 
-		for(size_t n = 0; n < 2; ++n) {
+		for( size_t n = 0; n < 2; ++n ) {
 			if( n > 0 ) {
 			if( n > 0 ) {
-				for(size_t i = 0; i < size; ++i ) 
-					out.push_back(in[i]+dir);
-			} else {
-				for(size_t i = size; i--; )
+				for( size_t i = 0; i < in.size(); ++i )
+					out.push_back(in[i] + dir);
+			}
+			else {
+				for( size_t i = in.size(); i--; )
 					out.push_back(in[i]);
 					out.push_back(in[i]);
 			}
 			}
 
 
-			curmesh.vertcnt.push_back(size);
-			if(openings && size > 2) {
-				if(GenerateOpenings(*conv.apply_openings,nors,temp,true, true, dir)) {
+			curmesh.vertcnt.push_back(in.size());
+			if( openings && in.size() > 2 ) {
+				if( GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
 					++sides_with_v_openings;
 					++sides_with_v_openings;
 				}
 				}
 
 
@@ -672,7 +650,7 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
 		}
 		}
 	}
 	}
 
 
-	if(openings && ((sides_with_openings == 1 && sides_with_openings) || (sides_with_v_openings == 2 && sides_with_v_openings))) {
+	if( openings && ((sides_with_openings == 1 && sides_with_openings) || (sides_with_v_openings == 2 && sides_with_v_openings)) ) {
 		IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
 		IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
 	}
 	}
 
 
@@ -680,17 +658,58 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
 
 
 	// If this is an opening element, store both the extruded mesh and the 2D profile mesh
 	// If this is an opening element, store both the extruded mesh and the 2D profile mesh
 	// it was created from. Return an empty mesh to the caller.
 	// it was created from. Return an empty mesh to the caller.
-	if(collect_openings && !result.IsEmpty()) {
+	if( collect_openings && !result.IsEmpty() ) {
 		ai_assert(conv.collect_openings);
 		ai_assert(conv.collect_openings);
 		boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
 		boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
 		profile->Swap(result);
 		profile->Swap(result);
 
 
 		boost::shared_ptr<TempMesh> profile2D = boost::shared_ptr<TempMesh>(new TempMesh());
 		boost::shared_ptr<TempMesh> profile2D = boost::shared_ptr<TempMesh>(new TempMesh());
-		profile2D->Swap(meshout);
-		conv.collect_openings->push_back(TempOpening(&solid,dir,profile, profile2D));
+		profile2D->verts.insert(profile2D->verts.end(), in.begin(), in.end());
+		profile2D->vertcnt.push_back(in.size());
+		conv.collect_openings->push_back(TempOpening(&solid, dir, profile, profile2D));
 
 
 		ai_assert(result.IsEmpty());
 		ai_assert(result.IsEmpty());
-	} 
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result, 
+	ConversionData& conv, bool collect_openings)
+{
+	TempMesh meshout;
+	
+	// First read the profile description. 
+	if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
+		return;
+	}
+
+	IfcVector3 dir;
+	ConvertDirection(dir,solid.ExtrudedDirection);
+	dir *= solid.Depth;
+
+	// Some profiles bring their own holes, for which we need to provide a container. This all is somewhat backwards, 
+	// and there's still so many corner cases uncovered - we really need a generic solution to all of this hole carving.
+	std::vector<TempOpening> fisherPriceMyFirstOpenings;
+	std::vector<TempOpening>* oldApplyOpenings = conv.apply_openings;
+	if( const IfcArbitraryProfileDefWithVoids* const cprofile = solid.SweptArea->ToPtr<IfcArbitraryProfileDefWithVoids>() ) {
+		if( !cprofile->InnerCurves.empty() ) {
+			// read all inner curves and extrude them to form proper openings. 
+			std::vector<TempOpening>* oldCollectOpenings = conv.collect_openings;
+			conv.collect_openings = &fisherPriceMyFirstOpenings;
+
+			BOOST_FOREACH(const IfcCurve* curve, cprofile->InnerCurves) {
+				TempMesh curveMesh, tempMesh;
+				ProcessCurve(*curve, curveMesh, conv);
+				ProcessExtrudedArea(solid, curveMesh, dir, tempMesh, conv, true);
+			}
+			// and then apply those to the geometry we're about to generate
+			conv.apply_openings = conv.collect_openings;
+			conv.collect_openings = oldCollectOpenings;
+		}
+	}
+
+	ProcessExtrudedArea(solid, meshout, dir, result, conv, collect_openings);
+	conv.apply_openings = oldApplyOpenings;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -785,7 +804,7 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, unsigned int matid,
 	meshtmp->RemoveDegenerates();
 	meshtmp->RemoveDegenerates();
 
 
 	if(fix_orientation) {
 	if(fix_orientation) {
-		meshtmp->FixupFaceOrientation();
+//		meshtmp->FixupFaceOrientation();
 	}
 	}
 
 
 	aiMesh* const mesh = meshtmp->ToMesh();
 	aiMesh* const mesh = meshtmp->ToMesh();

+ 6 - 3
code/IFCLoader.cpp

@@ -680,10 +680,11 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
 	const STEP::DB::RefMap& refs = conv.db.GetRefs();
 	const STEP::DB::RefMap& refs = conv.db.GetRefs();
 
 
 	// skip over space and annotation nodes - usually, these have no meaning in Assimp's context
 	// skip over space and annotation nodes - usually, these have no meaning in Assimp's context
+	bool skipGeometry = false;
 	if(conv.settings.skipSpaceRepresentations) {
 	if(conv.settings.skipSpaceRepresentations) {
 		if(const IfcSpace* const space = el.ToPtr<IfcSpace>()) {
 		if(const IfcSpace* const space = el.ToPtr<IfcSpace>()) {
 			IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
 			IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
-			return NULL;
+			skipGeometry = true;
 		}
 		}
 	}
 	}
 
 
@@ -853,8 +854,10 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
 			conv.apply_openings = &openings;
 			conv.apply_openings = &openings;
 		}
 		}
 
 
-		ProcessProductRepresentation(el,nd.get(),subnodes,conv);
-		conv.apply_openings = conv.collect_openings = NULL;
+		if (!skipGeometry) {
+		  ProcessProductRepresentation(el,nd.get(),subnodes,conv);
+		  conv.apply_openings = conv.collect_openings = NULL;
+		}
 
 
 		if (subnodes.size()) {
 		if (subnodes.size()) {
 			nd->mChildren = new aiNode*[subnodes.size()]();
 			nd->mChildren = new aiNode*[subnodes.size()]();

File diff suppressed because it is too large
+ 1091 - 1464
code/IFCReaderGen.cpp


File diff suppressed because it is too large
+ 1278 - 1270
code/IFCReaderGen.h


+ 1 - 1
code/IFCUtil.cpp

@@ -236,7 +236,7 @@ IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const
 
 
 struct CompareVector
 struct CompareVector
 {
 {
-	bool operator () (const IfcVector3& a, const IfcVector3& b)
+	bool operator () (const IfcVector3& a, const IfcVector3& b) const
 	{
 	{
 		IfcVector3 d = a - b;
 		IfcVector3 d = a - b;
 		IfcFloat eps = 1e-6;
 		IfcFloat eps = 1e-6;

+ 1 - 0
code/IFCUtil.h

@@ -277,6 +277,7 @@ IfcFloat ConvertSIPrefix(const std::string& prefix);
 
 
 // IFCProfile.cpp
 // IFCProfile.cpp
 bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv);
 bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv);
+bool ProcessCurve(const IfcCurve& curve,  TempMesh& meshout, ConversionData& conv);
 
 
 // IFCMaterial.cpp
 // IFCMaterial.cpp
 unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat);
 unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat);

+ 53 - 47
code/ImporterRegistry.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -140,6 +140,9 @@ corresponding preprocessor flag to selectively disable formats.
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 #	include "OgreImporter.h"
 #	include "OgreImporter.h"
 #endif
 #endif
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+#   include "OpenGEXImporter.h"
+#endif
 #ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
 #ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
 #	include "MS3DLoader.h"
 #	include "MS3DLoader.h"
 #endif
 #endif
@@ -177,132 +180,135 @@ namespace Assimp {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 {
 {
-	// ----------------------------------------------------------------------------
-	// Add an instance of each worker class here
-	// (register_new_importers_here)
-	// ----------------------------------------------------------------------------
-	out.reserve(64);
+    // ----------------------------------------------------------------------------
+    // Add an instance of each worker class here
+    // (register_new_importers_here)
+    // ----------------------------------------------------------------------------
+    out.reserve(64);
 #if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
-	out.push_back( new XFileImporter());
+    out.push_back( new XFileImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
-	out.push_back( new ObjFileImporter());
+    out.push_back( new ObjFileImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
-	out.push_back( new Discreet3DSImporter());
+    out.push_back( new Discreet3DSImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
-	out.push_back( new MD3Importer());
+    out.push_back( new MD3Importer());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
-	out.push_back( new MD2Importer());
+    out.push_back( new MD2Importer());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
-	out.push_back( new PLYImporter());
+    out.push_back( new PLYImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
-	out.push_back( new MDLImporter());
+    out.push_back( new MDLImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
-	out.push_back( new ASEImporter());
+    out.push_back( new ASEImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
-	out.push_back( new HMPImporter());
+    out.push_back( new HMPImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
-	out.push_back( new SMDImporter());
+    out.push_back( new SMDImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
-	out.push_back( new MDCImporter());
+    out.push_back( new MDCImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
-	out.push_back( new MD5Importer());
+    out.push_back( new MD5Importer());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
-	out.push_back( new STLImporter());
+    out.push_back( new STLImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
-	out.push_back( new LWOImporter());
+    out.push_back( new LWOImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
-	out.push_back( new DXFImporter());
+    out.push_back( new DXFImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
-	out.push_back( new NFFImporter());
+    out.push_back( new NFFImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
-	out.push_back( new RAWImporter());
+    out.push_back( new RAWImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
-	out.push_back( new OFFImporter());
+    out.push_back( new OFFImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
-	out.push_back( new AC3DImporter());
+    out.push_back( new AC3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
-	out.push_back( new BVHLoader());
+    out.push_back( new BVHLoader());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
-	out.push_back( new IRRMeshImporter());
+    out.push_back( new IRRMeshImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
-	out.push_back( new IRRImporter());
+    out.push_back( new IRRImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
-	out.push_back( new Q3DImporter());
+    out.push_back( new Q3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
-	out.push_back( new B3DImporter());
+    out.push_back( new B3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
-	out.push_back( new ColladaLoader());
+    out.push_back( new ColladaLoader());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
-	out.push_back( new TerragenImporter());
+    out.push_back( new TerragenImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
-	out.push_back( new CSMImporter());
+    out.push_back( new CSMImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
-	out.push_back( new UnrealImporter());
+    out.push_back( new UnrealImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
-	out.push_back( new LWSImporter());
+    out.push_back( new LWSImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
-	out.push_back( new Ogre::OgreImporter());
+    out.push_back( new Ogre::OgreImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OPENGEX_IMPORTER )
+    out.push_back( new OpenGEX::OpenGEXImporter() );
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
-	out.push_back( new MS3DImporter());
+    out.push_back( new MS3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
-	out.push_back( new COBImporter());
+    out.push_back( new COBImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
-	out.push_back( new BlenderImporter());
+    out.push_back( new BlenderImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
-	out.push_back( new Q3BSPFileImporter() );
+    out.push_back( new Q3BSPFileImporter() );
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
-	out.push_back( new NDOImporter() );
+    out.push_back( new NDOImporter() );
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
-	out.push_back( new IFCImporter() );
+    out.push_back( new IFCImporter() );
 #endif
 #endif
 #if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
 #if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
-	out.push_back( new XGLImporter() );
+    out.push_back( new XGLImporter() );
 #endif
 #endif
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
-	out.push_back( new FBXImporter() );
+    out.push_back( new FBXImporter() );
 #endif
 #endif
 #if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
 #if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
-	out.push_back( new AssbinImporter() );
+    out.push_back( new AssbinImporter() );
 #endif
 #endif
 
 
 #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
 #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
-	out.push_back( new C4DImporter() );
+    out.push_back( new C4DImporter() );
 #endif
 #endif
 }
 }
 
 
-}
+} // namespace Assimp

+ 1 - 1
code/ObjExporter.cpp

@@ -59,7 +59,7 @@ namespace Assimp	{
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
-void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	ObjExporter exporter(pFile, pScene);
 	ObjExporter exporter(pFile, pScene);

+ 520 - 519
code/ObjFileImporter.cpp

@@ -54,16 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 
 
 static const aiImporterDesc desc = {
 static const aiImporterDesc desc = {
-	"Wavefront Object Importer",
-	"",
-	"",
-	"surfaces not supported",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"obj"
+    "Wavefront Object Importer",
+    "",
+    "",
+    "surfaces not supported",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "obj"
 };
 };
 
 
 static const unsigned int ObjMinSize = 16;
 static const unsigned int ObjMinSize = 16;
@@ -75,99 +75,99 @@ using namespace std;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Default constructor
 //	Default constructor
 ObjFileImporter::ObjFileImporter() :
 ObjFileImporter::ObjFileImporter() :
-	m_Buffer(),	
-	m_pRootObject( NULL ),
-	m_strAbsPath( "" )
+    m_Buffer(),	
+    m_pRootObject( NULL ),
+    m_strAbsPath( "" )
 {
 {
     DefaultIOSystem io;
     DefaultIOSystem io;
-	m_strAbsPath = io.getOsSeparator();
+    m_strAbsPath = io.getOsSeparator();
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Destructor.
 //	Destructor.
 ObjFileImporter::~ObjFileImporter()
 ObjFileImporter::~ObjFileImporter()
 {
 {
-	delete m_pRootObject;
-	m_pRootObject = NULL;
+    delete m_pRootObject;
+    m_pRootObject = NULL;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Returns true, if file is an obj file.
 //	Returns true, if file is an obj file.
 bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem*  pIOHandler , bool checkSig ) const
 bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem*  pIOHandler , bool checkSig ) const
 {
 {
-	if(!checkSig) //Check File Extension
-	{
-		return SimpleExtensionCheck(pFile,"obj");
-	}
-	else //Check file Header
-	{
-		static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
-		return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
-	}
+    if(!checkSig) //Check File Extension
+    {
+        return SimpleExtensionCheck(pFile,"obj");
+    }
+    else //Check file Header
+    {
+        static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
+        return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const aiImporterDesc* ObjFileImporter::GetInfo () const
 const aiImporterDesc* ObjFileImporter::GetInfo () const
 {
 {
-	return &desc;
+    return &desc;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Obj-file import implementation
 //	Obj-file import implementation
 void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 {    
 {    
-	// Read file into memory
-	const std::string mode = "rb";
-	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
+    // Read file into memory
+    const std::string mode = "rb";
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
     if( !file.get() ) {
     if( !file.get() ) {
         throw DeadlyImportError( "Failed to open file " + pFile + "." );
         throw DeadlyImportError( "Failed to open file " + pFile + "." );
     }
     }
 
 
-	// Get the file-size and validate it, throwing an exception when fails
-	size_t fileSize = file->FileSize();
+    // Get the file-size and validate it, throwing an exception when fails
+    size_t fileSize = file->FileSize();
     if( fileSize < ObjMinSize ) {
     if( fileSize < ObjMinSize ) {
-		throw DeadlyImportError( "OBJ-file is too small.");
+        throw DeadlyImportError( "OBJ-file is too small.");
+    }
+
+    // Allocate buffer and read file into it
+    TextFileToBuffer(file.get(),m_Buffer);
+
+    // Get the model name
+    std::string  strModelName;
+    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;
+    }
+
+    // process all '\'
+    std::vector<char> ::iterator iter = m_Buffer.begin();
+    while (iter != m_Buffer.end())
+    {
+        if (*iter == '\\')
+        {
+            // remove '\'
+            iter = m_Buffer.erase(iter);
+            // remove next character
+            while (*iter == '\r' || *iter == '\n')
+                iter = m_Buffer.erase(iter);
+        }
+        else
+            ++iter;
+    }
+
+    // parse the file into a temporary representation
+    ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
+
+    // And create the proper return structures out of it
+    CreateDataFromImport(parser.GetModel(), pScene);
 
 
-	// Allocate buffer and read file into it
-	TextFileToBuffer(file.get(),m_Buffer);
-
-	// Get the model name
-	std::string  strModelName;
-	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;
-	}
-
-	// process all '\'
-	std::vector<char> ::iterator iter = m_Buffer.begin();
-	while (iter != m_Buffer.end())
-	{
-		if (*iter == '\\')
-		{
-			// remove '\'
-			iter = m_Buffer.erase(iter);
-			// remove next character
-			while (*iter == '\r' || *iter == '\n')
-				iter = m_Buffer.erase(iter);
-		}
-		else
-			++iter;
-	}
-
-	// parse the file into a temporary representation
-	ObjFileParser parser(m_Buffer, strModelName, 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();
+    // Clean up allocated storage for the next import 
+    m_Buffer.clear();
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -176,182 +176,183 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
     if( 0L == pModel ) {
     if( 0L == pModel ) {
         return;
         return;
     }
     }
-		
-	// Create the root node of the scene
-	pScene->mRootNode = new aiNode;
-	if ( !pModel->m_ModelName.empty() )
-	{
-		// Set the name of the scene
-		pScene->mRootNode->mName.Set(pModel->m_ModelName);
-	}
-	else
-	{
-		// This is a fatal error, so break down the application
-		ai_assert(false);
-	} 
-
-	// Create nodes for the whole scene	
-	std::vector<aiMesh*> MeshArray;
-	for (size_t index = 0; index < pModel->m_Objects.size(); index++)
-	{
-		createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
-	}
-
-	// Create mesh pointer buffer for this scene
-	if (pScene->mNumMeshes > 0)
-	{
-		pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
-		for (size_t index =0; index < MeshArray.size(); index++)
-		{
-			pScene->mMeshes [ index ] = MeshArray[ index ];
-		}
-	}
-
-	// Create all materials
-	createMaterials( pModel, pScene );
+        
+    // Create the root node of the scene
+    pScene->mRootNode = new aiNode;
+    if ( !pModel->m_ModelName.empty() )
+    {
+        // Set the name of the scene
+        pScene->mRootNode->mName.Set(pModel->m_ModelName);
+    }
+    else
+    {
+        // This is a fatal error, so break down the application
+        ai_assert(false);
+    } 
+
+    // Create nodes for the whole scene	
+    std::vector<aiMesh*> MeshArray;
+    for (size_t index = 0; index < pModel->m_Objects.size(); index++)
+    {
+        createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
+    }
+
+    // Create mesh pointer buffer for this scene
+    if (pScene->mNumMeshes > 0)
+    {
+        pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
+        for (size_t index =0; index < MeshArray.size(); index++)
+        {
+            pScene->mMeshes[ index ] = MeshArray[ index ];
+        }
+    }
+
+    // Create all materials
+    createMaterials( pModel, pScene );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Creates all nodes of the model
 //	Creates all nodes of the model
 aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject, 
 aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject, 
-									 aiNode *pParent, aiScene* pScene, 
-									 std::vector<aiMesh*> &MeshArray )
+                                     aiNode *pParent, aiScene* pScene, 
+                                     std::vector<aiMesh*> &MeshArray )
 {
 {
-	ai_assert( NULL != pModel );
+    ai_assert( NULL != pModel );
     if( NULL == pObject ) {
     if( NULL == pObject ) {
         return NULL;
         return NULL;
     }
     }
-	
-	// Store older mesh size to be able to computes mesh offsets for new mesh instances
-	const size_t oldMeshSize = MeshArray.size();
-	aiNode *pNode = new aiNode;
-
-	pNode->mName = pObject->m_strObjName;
-	
-	// If we have a parent node, store it
+    
+    // Store older mesh size to be able to computes mesh offsets for new mesh instances
+    const size_t oldMeshSize = MeshArray.size();
+    aiNode *pNode = new aiNode;
+
+    pNode->mName = pObject->m_strObjName;
+    
+    // If we have a parent node, store it
     if( pParent != NULL ) {
     if( pParent != NULL ) {
         appendChildToParentNode( pParent, pNode );
         appendChildToParentNode( pParent, pNode );
     }
     }
 
 
-	for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
-	{
-		unsigned int meshId = pObject->m_Meshes[ i ];
-		aiMesh *pMesh = createTopology( pModel, pObject, meshId );	
+    for ( size_t i=0; i< pObject->m_Meshes.size(); i++ )
+    {
+        unsigned int meshId = pObject->m_Meshes[ i ];
+        aiMesh *pMesh = createTopology( pModel, pObject, meshId );	
         if( pMesh && pMesh->mNumFaces > 0 ) {
         if( pMesh && pMesh->mNumFaces > 0 ) {
-			MeshArray.push_back( pMesh );
-		}
-	}
-
-	// Create all nodes from the sub-objects stored in the current object
-	if ( !pObject->m_SubObjects.empty() )
-	{
-		size_t numChilds = pObject->m_SubObjects.size();
-		pNode->mNumChildren = static_cast<unsigned int>( numChilds );
-		pNode->mChildren = new aiNode*[ numChilds ];
-		pNode->mNumMeshes = 1;
-		pNode->mMeshes = new unsigned int[ 1 ];
-	}
-
-	// Set mesh instances into scene- and node-instances
-	const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
-	if ( meshSizeDiff > 0 )
-	{
-		pNode->mMeshes = new unsigned int[ meshSizeDiff ];
-		pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
-		size_t index = 0;
-		for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
-		{
-			pNode->mMeshes[ index ] = pScene->mNumMeshes;
-			pScene->mNumMeshes++;
-			index++;
-		}
-	}
-	
-	return pNode;
+            MeshArray.push_back( pMesh );
+        }
+    }
+
+    // Create all nodes from the sub-objects stored in the current object
+    if ( !pObject->m_SubObjects.empty() )
+    {
+        size_t numChilds = pObject->m_SubObjects.size();
+        pNode->mNumChildren = static_cast<unsigned int>( numChilds );
+        pNode->mChildren = new aiNode*[ numChilds ];
+        pNode->mNumMeshes = 1;
+        pNode->mMeshes = new unsigned int[ 1 ];
+    }
+
+    // Set mesh instances into scene- and node-instances
+    const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
+    if ( meshSizeDiff > 0 )
+    {
+        pNode->mMeshes = new unsigned int[ meshSizeDiff ];
+        pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
+        size_t index = 0;
+        for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
+        {
+            pNode->mMeshes[ index ] = pScene->mNumMeshes;
+            pScene->mNumMeshes++;
+            index++;
+        }
+    }
+    
+    return pNode;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Create topology data
 //	Create topology data
 aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData, 
 aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData, 
-                                         unsigned int uiMeshIndex )
+                                         unsigned int meshIndex )
 {
 {
-	// Checking preconditions
-	ai_assert( NULL != pModel );
+    // Checking preconditions
+    ai_assert( NULL != pModel );
+    
     if( NULL == pData ) {
     if( NULL == pData ) {
         return NULL;
         return NULL;
     }
     }
 
 
-	// Create faces
-	ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
+    // Create faces
+    ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ meshIndex ];
     if( !pObjMesh ) {
     if( !pObjMesh ) {
         return NULL;
         return NULL;
     }
     }
     ai_assert( NULL != pObjMesh );
     ai_assert( NULL != pObjMesh );
     aiMesh* pMesh = new aiMesh;
     aiMesh* pMesh = new aiMesh;
-	for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
-	{
-		ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
+    for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
+    {
+        ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
         ai_assert( NULL != inp  );
         ai_assert( NULL != inp  );
 
 
-		if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
-			pMesh->mNumFaces += inp->m_pVertices->size() - 1;
-			pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-		} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
-			pMesh->mNumFaces += inp->m_pVertices->size();
-			pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-		} else {
-			++pMesh->mNumFaces;
-			if (inp->m_pVertices->size() > 3) {
-				pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-			} else {
-				pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-			}
-		}
-	}
-
-	unsigned int uiIdxCount( 0u );
-	if ( pMesh->mNumFaces > 0 )
-	{
-		pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
-		if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial )
-		{
-			pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
-		}
-
-		unsigned int outIndex( 0 );
-
-		// Copy all data from all stored meshes
-		for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
-		{
-			ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
-			if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
-				for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
-					aiFace& f = pMesh->mFaces[ outIndex++ ];
-					uiIdxCount += f.mNumIndices = 2;
-					f.mIndices = new unsigned int[2];
-				}
-				continue;
-			}
-			else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
-				for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
-					aiFace& f = pMesh->mFaces[ outIndex++ ];
-					uiIdxCount += f.mNumIndices = 1;
-					f.mIndices = new unsigned int[1];
-				}
-				continue;
-			}
-
-			aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
-			const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
-			uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
-			if (pFace->mNumIndices > 0) {
-				pFace->mIndices = new unsigned int[ uiNumIndices ];			
-			}
-		}
-	}
-
-	// Create mesh vertices
-	createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
+        if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+            pMesh->mNumFaces += inp->m_pVertices->size() - 1;
+            pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+        } else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+            pMesh->mNumFaces += inp->m_pVertices->size();
+            pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+        } else {
+            ++pMesh->mNumFaces;
+            if (inp->m_pVertices->size() > 3) {
+                pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+            } else {
+                pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+            }
+        }
+    }
+
+    unsigned int uiIdxCount( 0u );
+    if ( pMesh->mNumFaces > 0 )
+    {
+        pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
+        if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial )
+        {
+            pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
+        }
+
+        unsigned int outIndex( 0 );
+
+        // Copy all data from all stored meshes
+        for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
+        {
+            ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+            if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+                for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
+                    aiFace& f = pMesh->mFaces[ outIndex++ ];
+                    uiIdxCount += f.mNumIndices = 2;
+                    f.mIndices = new unsigned int[2];
+                }
+                continue;
+            }
+            else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+                for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
+                    aiFace& f = pMesh->mFaces[ outIndex++ ];
+                    uiIdxCount += f.mNumIndices = 1;
+                    f.mIndices = new unsigned int[1];
+                }
+                continue;
+            }
+
+            aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
+            const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
+            uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
+            if (pFace->mNumIndices > 0) {
+                pFace->mIndices = new unsigned int[ uiNumIndices ];			
+            }
+        }
+    }
+
+    // Create mesh vertices
+    createVertexArray(pModel, pData, meshIndex, pMesh, uiIdxCount);
 
 
     return pMesh;
     return pMesh;
 }
 }
@@ -359,335 +360,335 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Creates a vertex array
 //	Creates a vertex array
 void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, 
 void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, 
-										const ObjFile::Object* pCurrentObject, 
-										unsigned int uiMeshIndex,
-										aiMesh* pMesh,
-										unsigned int uiIdxCount)
+                                        const ObjFile::Object* pCurrentObject, 
+                                        unsigned int uiMeshIndex,
+                                        aiMesh* pMesh,
+                                        unsigned int numIndices)
 {
 {
-	// Checking preconditions
-	ai_assert( NULL != pCurrentObject );
-	
-	// Break, if no faces are stored in object
-	if ( pCurrentObject->m_Meshes.empty() )
-		return;
-
-	// Get current mesh
-	ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
-	if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
-		return;
-
-	// Copy vertices of this mesh instance
-	pMesh->mNumVertices = uiIdxCount;
-	pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
-	
-	// Allocate buffer for normal vectors
-	if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
-		pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
-	
-	// Allocate buffer for texture coordinates
-	if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
-	{
-		pMesh->mNumUVComponents[ 0 ] = 2;
-		pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
-	}
-	
-	// Copy vertices, normals and textures into aiMesh instance
-	unsigned int newIndex = 0, outIndex = 0;
-	for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
-	{
-		// Get source face
-		ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; 
-
-		// Copy all index arrays
-		for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
-		{
-			const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
-			if ( vertex >= pModel->m_Vertices.size() ) 
-				throw DeadlyImportError( "OBJ: vertex index out of range" );
-			
-			pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
-			
-			// Copy all normals 
-			if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
-			{
-				const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
-				if ( normal >= pModel->m_Normals.size() )
-					throw DeadlyImportError("OBJ: vertex normal index out of range");
-
-				pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
-			}
-			
-			// Copy all texture coordinates
-			if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
-			{
-				const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
-				ai_assert( tex < pModel->m_TextureCoord.size() );
-					
-				if ( tex >= pModel->m_TextureCoord.size() )
-					throw DeadlyImportError("OBJ: texture coordinate index out of range");
-
-				const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
+    // Checking preconditions
+    ai_assert( NULL != pCurrentObject );
+    
+    // Break, if no faces are stored in object
+    if ( pCurrentObject->m_Meshes.empty() )
+        return;
+
+    // Get current mesh
+    ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
+    if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
+        return;
+
+    // Copy vertices of this mesh instance
+    pMesh->mNumVertices = numIndices;
+    pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
+    
+    // Allocate buffer for normal vectors
+    if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
+        pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
+    
+    // Allocate buffer for texture coordinates
+    if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
+    {
+        pMesh->mNumUVComponents[ 0 ] = 2;
+        pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
+    }
+    
+    // Copy vertices, normals and textures into aiMesh instance
+    unsigned int newIndex = 0, outIndex = 0;
+    for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
+    {
+        // Get source face
+        ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; 
+
+        // Copy all index arrays
+        for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
+        {
+            const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
+            if ( vertex >= pModel->m_Vertices.size() ) 
+                throw DeadlyImportError( "OBJ: vertex index out of range" );
+            
+            pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
+            
+            // Copy all normals 
+            if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
+            {
+                const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
+                if ( normal >= pModel->m_Normals.size() )
+                    throw DeadlyImportError("OBJ: vertex normal index out of range");
+
+                pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
+            }
+            
+            // Copy all texture coordinates
+            if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
+            {
+                const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
+                ai_assert( tex < pModel->m_TextureCoord.size() );
+                    
+                if ( tex >= pModel->m_TextureCoord.size() )
+                    throw DeadlyImportError("OBJ: texture coordinate index out of range");
+
+                const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
                 pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
                 pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
-			}
-
-			ai_assert( pMesh->mNumVertices > newIndex );
-
-			// Get destination face
-			aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
-
-			const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 ); 
-			if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) 
-			{
-				pDestFace->mIndices[ outVertexIndex ] = newIndex;
-				outVertexIndex++;
-			}
-
-			if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) 
-			{
-				outIndex++;
-				outVertexIndex = 0;
-			}
-			else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) 
-			{
-				outVertexIndex = 0;
-
-				if(!last) 
-					outIndex++;
-
-				if (vertexIndex) {
-					if(!last) {
-						pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
-						if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
-							pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
-						}
-						if ( !pModel->m_TextureCoord.empty() ) {
-							for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
-								pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
-							}
-						}
-						++newIndex;
-					}
-
-					pDestFace[-1].mIndices[1] = newIndex;
-				}
-			}
-			else if (last) {
-				outIndex++;
-			}
-			++newIndex;
-		}
-	}	
+            }
+
+            ai_assert( pMesh->mNumVertices > newIndex );
+
+            // Get destination face
+            aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
+
+            const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 ); 
+            if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) 
+            {
+                pDestFace->mIndices[ outVertexIndex ] = newIndex;
+                outVertexIndex++;
+            }
+
+            if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) 
+            {
+                outIndex++;
+                outVertexIndex = 0;
+            }
+            else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) 
+            {
+                outVertexIndex = 0;
+
+                if(!last) 
+                    outIndex++;
+
+                if (vertexIndex) {
+                    if(!last) {
+                        pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
+                        if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
+                            pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
+                        }
+                        if ( !pModel->m_TextureCoord.empty() ) {
+                            for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
+                                pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
+                            }
+                        }
+                        ++newIndex;
+                    }
+
+                    pDestFace[-1].mIndices[1] = newIndex;
+                }
+            }
+            else if (last) {
+                outIndex++;
+            }
+            ++newIndex;
+        }
+    }	
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Counts all stored meshes 
 //	Counts all stored meshes 
 void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
 void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
 {
 {
-	iNumMeshes = 0;
-	if ( rObjects.empty() )	
-		return;
-
-	iNumMeshes += static_cast<unsigned int>( rObjects.size() );
-	for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
-		it != rObjects.end(); 
-		++it)
-	{
-		if (!(*it)->m_SubObjects.empty())
-		{
-			countObjects((*it)->m_SubObjects, iNumMeshes);
-		}
-	}
+    iNumMeshes = 0;
+    if ( rObjects.empty() )	
+        return;
+
+    iNumMeshes += static_cast<unsigned int>( rObjects.size() );
+    for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
+        it != rObjects.end(); 
+        ++it)
+    {
+        if (!(*it)->m_SubObjects.empty())
+        {
+            countObjects((*it)->m_SubObjects, iNumMeshes);
+        }
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	 Add clamp mode property to material if necessary 
 //	 Add clamp mode property to material if necessary 
 void ObjFileImporter::addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode)
 void ObjFileImporter::addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode)
 {
 {
-	ai_assert( NULL != mat);
-	mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
-	mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
+    ai_assert( NULL != mat);
+    mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
+    mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Creates the material 
 //	Creates the material 
 void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene )
 void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene )
 {
 {
-	ai_assert( NULL != pScene );
-	if ( NULL == pScene )
-		return;
-
-	const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
-	pScene->mNumMaterials = 0;
-	if ( pModel->m_MaterialLib.empty() ) {
-		DefaultLogger::get()->debug("OBJ: no materials specified");
-		return;
-	}
-	
-	pScene->mMaterials = new aiMaterial*[ numMaterials ];
-	for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
-	{		
-		// Store material name
-		std::map<std::string, ObjFile::Material*>::const_iterator it;
-		it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
-		
-		// No material found, use the default material
-		if ( pModel->m_MaterialMap.end() == it )
-			continue;
-
-		aiMaterial* mat = new aiMaterial;
-		ObjFile::Material *pCurrentMaterial = (*it).second;
-		mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
-
-		// convert illumination model
-		int sm = 0;
-		switch (pCurrentMaterial->illumination_model) 
-		{
-		case 0:
-			sm = aiShadingMode_NoShading;
-			break;
-		case 1:
-			sm = aiShadingMode_Gouraud;
-			break;
-		case 2:
-			sm = aiShadingMode_Phong;
-			break;
-		default:
-			sm = aiShadingMode_Gouraud;
-			DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)");
-		}
-	
-		mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
-
-		// multiplying the specular exponent with 2 seems to yield better results
-		pCurrentMaterial->shineness *= 4.f;
-
-		// Adding material colors
-		mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
-		mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
-		mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
-		mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE );
-		mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
-		mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
-
-		// Adding refraction index
-		mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
-
-		// Adding textures
-		if ( 0 != pCurrentMaterial->texture.length ) 
-		{
-			mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureAmbient.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureEmissive.length )
-			mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
-
-		if ( 0 != pCurrentMaterial->textureSpecular.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureBump.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureNormal.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureDisp.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureOpacity.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureSpecularity.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
-			}
-		}
-		
-		// Store material property info in material array in scene
-		pScene->mMaterials[ pScene->mNumMaterials ] = mat;
-		pScene->mNumMaterials++;
-	}
-	
-	// Test number of created materials.
-	ai_assert( pScene->mNumMaterials == numMaterials );
+    ai_assert( NULL != pScene );
+    if ( NULL == pScene )
+        return;
+
+    const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
+    pScene->mNumMaterials = 0;
+    if ( pModel->m_MaterialLib.empty() ) {
+        DefaultLogger::get()->debug("OBJ: no materials specified");
+        return;
+    }
+    
+    pScene->mMaterials = new aiMaterial*[ numMaterials ];
+    for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
+    {		
+        // Store material name
+        std::map<std::string, ObjFile::Material*>::const_iterator it;
+        it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
+        
+        // No material found, use the default material
+        if ( pModel->m_MaterialMap.end() == it )
+            continue;
+
+        aiMaterial* mat = new aiMaterial;
+        ObjFile::Material *pCurrentMaterial = (*it).second;
+        mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
+
+        // convert illumination model
+        int sm = 0;
+        switch (pCurrentMaterial->illumination_model) 
+        {
+        case 0:
+            sm = aiShadingMode_NoShading;
+            break;
+        case 1:
+            sm = aiShadingMode_Gouraud;
+            break;
+        case 2:
+            sm = aiShadingMode_Phong;
+            break;
+        default:
+            sm = aiShadingMode_Gouraud;
+            DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)");
+        }
+    
+        mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
+
+        // multiplying the specular exponent with 2 seems to yield better results
+        pCurrentMaterial->shineness *= 4.f;
+
+        // Adding material colors
+        mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
+        mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
+        mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
+        mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE );
+        mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
+        mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
+
+        // Adding refraction index
+        mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
+
+        // Adding textures
+        if ( 0 != pCurrentMaterial->texture.length ) 
+        {
+            mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureAmbient.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureEmissive.length )
+            mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
+
+        if ( 0 != pCurrentMaterial->textureSpecular.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureBump.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureNormal.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureDisp.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureOpacity.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureSpecularity.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
+            }
+        }
+        
+        // Store material property info in material array in scene
+        pScene->mMaterials[ pScene->mNumMaterials ] = mat;
+        pScene->mNumMaterials++;
+    }
+    
+    // Test number of created materials.
+    ai_assert( pScene->mNumMaterials == numMaterials );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Appends this node to the parent node
 //	Appends this node to the parent node
 void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
 void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
 {
 {
-	// Checking preconditions
-	ai_assert( NULL != pParent );
-	ai_assert( NULL != pChild );
-
-	// Assign parent to child
-	pChild->mParent = pParent;
-	
-	// If already children was assigned to the parent node, store them in a 
-	std::vector<aiNode*> temp;
-	if (pParent->mChildren != NULL)
-	{
-		ai_assert( 0 != pParent->mNumChildren );
-		for (size_t index = 0; index < pParent->mNumChildren; index++)
-		{
-			temp.push_back(pParent->mChildren [ index ] );
-		}
-		delete [] pParent->mChildren;
-	}
-	
-	// Copy node instances into parent node
-	pParent->mNumChildren++;
-	pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
-	for (size_t index = 0; index < pParent->mNumChildren-1; index++)
-	{
-		pParent->mChildren[ index ] = temp [ index ];
-	}
-	pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
+    // Checking preconditions
+    ai_assert( NULL != pParent );
+    ai_assert( NULL != pChild );
+
+    // Assign parent to child
+    pChild->mParent = pParent;
+    
+    // If already children was assigned to the parent node, store them in a 
+    std::vector<aiNode*> temp;
+    if (pParent->mChildren != NULL)
+    {
+        ai_assert( 0 != pParent->mNumChildren );
+        for (size_t index = 0; index < pParent->mNumChildren; index++)
+        {
+            temp.push_back(pParent->mChildren [ index ] );
+        }
+        delete [] pParent->mChildren;
+    }
+    
+    // Copy node instances into parent node
+    pParent->mNumChildren++;
+    pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
+    for (size_t index = 0; index < pParent->mNumChildren-1; index++)
+    {
+        pParent->mChildren[ index ] = temp [ index ];
+    }
+    pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 39 - 37
code/ObjFileImporter.h

@@ -65,57 +65,59 @@ struct Model;
 class ObjFileImporter : public BaseImporter
 class ObjFileImporter : public BaseImporter
 {	
 {	
 public:
 public:
-	///	\brief	Default constructor
-	ObjFileImporter();
+    ///	\brief	Default constructor
+    ObjFileImporter();
 
 
-	///	\brief	Destructor
-	~ObjFileImporter();
+    ///	\brief	Destructor
+    ~ObjFileImporter();
 
 
 public:
 public:
-	/// \brief	Returns whether the class can handle the format of the given file. 
-	/// \remark	See BaseImporter::CanRead() for details.
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+    /// \brief	Returns whether the class can handle the format of the given file. 
+    /// \remark	See BaseImporter::CanRead() for details.
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
 
 
 private:
 private:
 
 
-	//! \brief	Appends the supported extension.
-	const aiImporterDesc* GetInfo () const;
+    //! \brief	Appends the supported extension.
+    const aiImporterDesc* GetInfo () const;
 
 
-	//!	\brief	File import implementation.
-	void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
-	
-	//!	\brief	Create the data from imported content.
-	void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
-	
-	//!	\brief	Creates all nodes stored in imported content.
-	aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
-		aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
+    //!	\brief	File import implementation.
+    void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+    
+    //!	\brief	Create the data from imported content.
+    void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
+    
+    //!	\brief	Creates all nodes stored in imported content.
+    aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
+        aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
 
 
-	//!	\brief	Creates topology data like faces and meshes for the geometry.
+    //!	\brief	Creates topology data like faces and meshes for the geometry.
     aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
     aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
-		unsigned int uiMeshIndex );	
-	
-	//!	\brief	Creates vertices from model.
-	void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
-		unsigned int uiMeshIndex, aiMesh* pMesh,unsigned int uiIdxCount);
+        unsigned int uiMeshIndex );	
+    
+    //!	\brief	Creates vertices from model.
+    void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
+        unsigned int uiMeshIndex, aiMesh* pMesh, unsigned int numIndices );
 
 
-	//!	\brief	Object counter helper method.
-	void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);
+    //!	\brief	Object counter helper method.
+    void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);
 
 
-	//!	\brief	Material creation.
-	void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
-	void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1);
+    //!	\brief	Material creation.
+    void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
+    
+    ///	@brief  Adds special property for the used texture mapping mode of the model.
+    void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1);
 
 
-	//!	\brief	Appends a child node to a parent node and updates the data structures.
-	void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
+    //!	\brief	Appends a child node to a parent node and updates the data structures.
+    void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
 
 
 private:
 private:
-	//!	Data buffer
-	std::vector<char> m_Buffer;
-	//!	Pointer to root object instance
-	ObjFile::Object *m_pRootObject;
-	//!	Absolute pathname of model in file system
-	std::string m_strAbsPath;
+    //!	Data buffer
+    std::vector<char> m_Buffer;
+    //!	Pointer to root object instance
+    ObjFile::Object *m_pRootObject;
+    //!	Absolute pathname of model in file system
+    std::string m_strAbsPath;
 };
 };
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 486 - 486
code/ObjFileParser.cpp

@@ -62,177 +62,177 @@ const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Constructor with loaded data and directories.
 //	Constructor with loaded data and directories.
 ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
 ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
-	m_DataIt(Data.begin()),
-	m_DataItEnd(Data.end()),
-	m_pModel(NULL),
-	m_uiLine(0),
-	m_pIO( 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;
-	
+    // Create the model instance to store all the data
+    m_pModel = new ObjFile::Model();
+    m_pModel->m_ModelName = strModelName;
+    
     // create default material and store it
     // create default material and store it
-	m_pModel->m_pDefaultMaterial = new ObjFile::Material();
-	m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_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_MaterialLib.push_back( DEFAULT_MATERIAL );
-	m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
-	
-	// Start parsing the file
-	parseFile();
+    m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
+    
+    // Start parsing the file
+    parseFile();
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Destructor
 //	Destructor
 ObjFileParser::~ObjFileParser()
 ObjFileParser::~ObjFileParser()
 {
 {
-	delete m_pModel;
-	m_pModel = NULL;
+    delete m_pModel;
+    m_pModel = NULL;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Returns a pointer to the model instance.
 //	Returns a pointer to the model instance.
 ObjFile::Model *ObjFileParser::GetModel() const
 ObjFile::Model *ObjFileParser::GetModel() const
 {
 {
-	return m_pModel;
+    return m_pModel;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	File parsing method.
 //	File parsing method.
 void ObjFileParser::parseFile()
 void ObjFileParser::parseFile()
 {
 {
-	if (m_DataIt == m_DataItEnd)
-		return;
-
-	while (m_DataIt != m_DataItEnd)
-	{
-		switch (*m_DataIt)
-		{
-		case 'v': // Parse a vertex texture coordinate
-			{
-				++m_DataIt;
-				if (*m_DataIt == ' ' || *m_DataIt == '\t') {
-					// read in vertex definition
-					getVector3(m_pModel->m_Vertices);
-				} else if (*m_DataIt == 't') {
-					// read in texture coordinate ( 2D or 3D )
+    if (m_DataIt == m_DataItEnd)
+        return;
+
+    while (m_DataIt != m_DataItEnd)
+    {
+        switch (*m_DataIt)
+        {
+        case 'v': // Parse a vertex texture coordinate
+            {
+                ++m_DataIt;
+                if (*m_DataIt == ' ' || *m_DataIt == '\t') {
+                    // read in vertex definition
+                    getVector3(m_pModel->m_Vertices);
+                } else if (*m_DataIt == 't') {
+                    // read in texture coordinate ( 2D or 3D )
                                         ++m_DataIt;
                                         ++m_DataIt;
                                         getVector( m_pModel->m_TextureCoord );
                                         getVector( m_pModel->m_TextureCoord );
-				} else if (*m_DataIt == 'n') {
-					// Read in normal vector definition
-					++m_DataIt;
-					getVector3( m_pModel->m_Normals );
-				}
-			}
-			break;
-
-		case 'p': // Parse a face, line or point statement
-		case 'l':
-		case 'f':
-			{
-				getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l' 
-					? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
-			}
-			break;
-
-		case '#': // Parse a comment
-			{
-				getComment();
-			}
-			break;
-
-		case 'u': // Parse a material desc. setter
-			{
-				getMaterialDesc();
-			}
-			break;
-
-		case 'm': // Parse a material library or merging group ('mg')
-			{
-				if (*(m_DataIt + 1) == 'g')
-					getGroupNumberAndResolution();
-				else
-					getMaterialLib();
-			}
-			break;
-
-		case 'g': // Parse group name
-			{
-				getGroupName();
-			}
-			break;
-
-		case 's': // Parse group number
-			{
-				getGroupNumber();
-			}
-			break;
-
-		case 'o': // Parse object name
-			{
-				getObjectName();
-			}
-			break;
-		
-		default:
-			{
-				m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-			}
-			break;
-		}
-	}
+                } else if (*m_DataIt == 'n') {
+                    // Read in normal vector definition
+                    ++m_DataIt;
+                    getVector3( m_pModel->m_Normals );
+                }
+            }
+            break;
+
+        case 'p': // Parse a face, line or point statement
+        case 'l':
+        case 'f':
+            {
+                getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l' 
+                    ? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
+            }
+            break;
+
+        case '#': // Parse a comment
+            {
+                getComment();
+            }
+            break;
+
+        case 'u': // Parse a material desc. setter
+            {
+                getMaterialDesc();
+            }
+            break;
+
+        case 'm': // Parse a material library or merging group ('mg')
+            {
+                if (*(m_DataIt + 1) == 'g')
+                    getGroupNumberAndResolution();
+                else
+                    getMaterialLib();
+            }
+            break;
+
+        case 'g': // Parse group name
+            {
+                getGroupName();
+            }
+            break;
+
+        case 's': // Parse group number
+            {
+                getGroupNumber();
+            }
+            break;
+
+        case 'o': // Parse object name
+            {
+                getObjectName();
+            }
+            break;
+        
+        default:
+            {
+                m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+            }
+            break;
+        }
+    }
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Copy the next word in a temporary buffer
 //	Copy the next word in a temporary buffer
 void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 {
 {
-	size_t index = 0;
-	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
+    size_t index = 0;
+    m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
-		pBuffer[index] = *m_DataIt;
-		index++;
+        pBuffer[index] = *m_DataIt;
+        index++;
         if( index == length - 1 ) {
         if( index == length - 1 ) {
             break;
             break;
         }
         }
-		++m_DataIt;
-	}
+        ++m_DataIt;
+    }
 
 
-	ai_assert(index < length);
-	pBuffer[index] = '\0';
+    ai_assert(index < length);
+    pBuffer[index] = '\0';
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 // Copy the next line into a temporary buffer
 // Copy the next line into a temporary buffer
 void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 {
 {
-	size_t index = 0u;
-
-	// some OBJ files have line continuations using \ (such as in C++ et al)
-	bool continuation = false;
-	for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt) 
-	{
-		const char c = *m_DataIt;
-		if (c == '\\') {
-			continuation = true;
-			continue;
-		}
-		
-		if (c == '\n' || c == '\r') {
-			if(continuation) {
-				pBuffer[ index++ ] = ' ';
-				continue;
-			}
-			break;
-		}
-
-		continuation = false;
-		pBuffer[ index++ ] = c;
-	}
-	ai_assert(index < length);
-	pBuffer[ index ] = '\0';
+    size_t index = 0u;
+
+    // some OBJ files have line continuations using \ (such as in C++ et al)
+    bool continuation = false;
+    for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt) 
+    {
+        const char c = *m_DataIt;
+        if (c == '\\') {
+            continuation = true;
+            continue;
+        }
+        
+        if (c == '\n' || c == '\r') {
+            if(continuation) {
+                pBuffer[ index++ ] = ' ';
+                continue;
+            }
+            break;
+        }
+
+        continuation = false;
+        pBuffer[ index++ ] = c;
+    }
+    ai_assert(index < length);
+    pBuffer[ index ] = '\0';
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -273,391 +273,391 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new 3D vector instance
 //	Get values for a new 3D vector instance
 void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
 void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
-	float x, y, z;
-	copyNextWord(m_buffer, BUFFERSIZE);
-	x = (float) fast_atof(m_buffer);	
-	
-	copyNextWord(m_buffer, BUFFERSIZE);
-	y = (float) fast_atof(m_buffer);
+    float x, y, z;
+    copyNextWord(m_buffer, BUFFERSIZE);
+    x = (float) fast_atof(m_buffer);	
+    
+    copyNextWord(m_buffer, BUFFERSIZE);
+    y = (float) fast_atof(m_buffer);
 
 
     copyNextWord( m_buffer, BUFFERSIZE );
     copyNextWord( m_buffer, BUFFERSIZE );
     z = ( float ) fast_atof( m_buffer );
     z = ( float ) fast_atof( m_buffer );
 
 
-	point3d_array.push_back( aiVector3D( x, y, z ) );
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    point3d_array.push_back( aiVector3D( x, y, z ) );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new 2D vector instance
 //	Get values for a new 2D vector instance
 void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
 void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
-	float x, y;
-	copyNextWord(m_buffer, BUFFERSIZE);
-	x = (float) fast_atof(m_buffer);	
-	
-	copyNextWord(m_buffer, BUFFERSIZE);
-	y = (float) fast_atof(m_buffer);
+    float x, y;
+    copyNextWord(m_buffer, BUFFERSIZE);
+    x = (float) fast_atof(m_buffer);	
+    
+    copyNextWord(m_buffer, BUFFERSIZE);
+    y = (float) fast_atof(m_buffer);
 
 
-	point2d_array.push_back(aiVector2D(x, y));
+    point2d_array.push_back(aiVector2D(x, y));
 
 
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new face instance
 //	Get values for a new face instance
 void ObjFileParser::getFace(aiPrimitiveType type)
 void ObjFileParser::getFace(aiPrimitiveType type)
 {
 {
-	copyNextLine(m_buffer, BUFFERSIZE);
-	if (m_DataIt == m_DataItEnd)
-		return;
-
-	char *pPtr = m_buffer;
-	char *pEnd = &pPtr[BUFFERSIZE];
-	pPtr = getNextToken<char*>(pPtr, pEnd);
-	if (pPtr == pEnd || *pPtr == '\0')
-		return;
-
-	std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
-	std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
-	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
-	bool hasNormal = false;
-
-	const int vSize = m_pModel->m_Vertices.size();
-	const int vtSize = m_pModel->m_TextureCoord.size();
-	const int vnSize = m_pModel->m_Normals.size();
-
-	const bool vt = (!m_pModel->m_TextureCoord.empty());
-	const bool vn = (!m_pModel->m_Normals.empty());
-	int iStep = 0, iPos = 0;
-	while (pPtr != pEnd)
-	{
-		iStep = 1;
-
-		if (IsLineEnd(*pPtr))
-			break;
-
-		if (*pPtr=='/' )
-		{
-			if (type == aiPrimitiveType_POINT) {
-				DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
-			}
-			if (iPos == 0)
-			{
-				//if there are no texture coordinates in the file, but normals
-				if (!vt && vn) {
-					iPos = 1;
-					iStep++;
-				}
-			}
-			iPos++;
-		}
+    copyNextLine(m_buffer, BUFFERSIZE);
+    if (m_DataIt == m_DataItEnd)
+        return;
+
+    char *pPtr = m_buffer;
+    char *pEnd = &pPtr[BUFFERSIZE];
+    pPtr = getNextToken<char*>(pPtr, pEnd);
+    if (pPtr == pEnd || *pPtr == '\0')
+        return;
+
+    std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
+    std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
+    std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
+    bool hasNormal = false;
+
+    const int vSize = m_pModel->m_Vertices.size();
+    const int vtSize = m_pModel->m_TextureCoord.size();
+    const int vnSize = m_pModel->m_Normals.size();
+
+    const bool vt = (!m_pModel->m_TextureCoord.empty());
+    const bool vn = (!m_pModel->m_Normals.empty());
+    int iStep = 0, iPos = 0;
+    while (pPtr != pEnd)
+    {
+        iStep = 1;
+
+        if (IsLineEnd(*pPtr))
+            break;
+
+        if (*pPtr=='/' )
+        {
+            if (type == aiPrimitiveType_POINT) {
+                DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
+            }
+            if (iPos == 0)
+            {
+                //if there are no texture coordinates in the file, but normals
+                if (!vt && vn) {
+                    iPos = 1;
+                    iStep++;
+                }
+            }
+            iPos++;
+        }
         else if( IsSpaceOrNewLine( *pPtr ) )
         else if( IsSpaceOrNewLine( *pPtr ) )
-		{
-			iPos = 0;
-		}
-		else 
-		{
-			//OBJ USES 1 Base ARRAYS!!!!
-			const int iVal = atoi( pPtr );
-
-			// increment iStep position based off of the sign and # of digits
-			int tmp = iVal;
-			if (iVal < 0)
-			    ++iStep;
-			while ( ( tmp = tmp / 10 )!=0 )
-				++iStep;
-
-			if ( iVal > 0 )
-			{
-				// Store parsed index
-				if ( 0 == iPos )
-				{
-					pIndices->push_back( iVal-1 );
-				}
-				else if ( 1 == iPos )
-				{	
-					pTexID->push_back( iVal-1 );
-				}
-				else if ( 2 == iPos )
-				{
-					pNormalID->push_back( iVal-1 );
-					hasNormal = true;
-				}
-				else
-				{
-					reportErrorTokenInFace();
-				}
-			}
-			else if ( iVal < 0 )
-			{
-				// Store relatively index
-				if ( 0 == iPos )
-				{
-					pIndices->push_back( vSize + iVal );
-				}
-				else if ( 1 == iPos )
-				{
-					pTexID->push_back( vtSize + iVal );
-				}
-				else if ( 2 == iPos )
-				{
-					pNormalID->push_back( vnSize + iVal );
-					hasNormal = true;
-				}
-				else
-				{
-					reportErrorTokenInFace();
-				}
-			}
-		}
-		pPtr += iStep;
-	}
-
-	if ( pIndices->empty() ) 
-	{
-		DefaultLogger::get()->error("Obj: Ignoring empty face");
-		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-		return;
-	}
-
-	ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
-	
-	// Set active material, if one set
-	if (NULL != m_pModel->m_pCurrentMaterial) 
-		face->m_pMaterial = m_pModel->m_pCurrentMaterial;
-	else 
-		face->m_pMaterial = m_pModel->m_pDefaultMaterial;
-
-	// Create a default object, if nothing is there
-	if ( NULL == m_pModel->m_pCurrent )
-		createObject( "defaultobject" );
-	
-	// Assign face to mesh
-	if ( NULL == m_pModel->m_pCurrentMesh )
-	{
-		createMesh();
-	}
-	
-	// Store the face
-	m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
-	m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
-	m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); 
-	if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) 
-	{
-		m_pModel->m_pCurrentMesh->m_hasNormals = true;
-	}
-	// Skip the rest of the line
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+        {
+            iPos = 0;
+        }
+        else 
+        {
+            //OBJ USES 1 Base ARRAYS!!!!
+            const int iVal = atoi( pPtr );
+
+            // increment iStep position based off of the sign and # of digits
+            int tmp = iVal;
+            if (iVal < 0)
+                ++iStep;
+            while ( ( tmp = tmp / 10 )!=0 )
+                ++iStep;
+
+            if ( iVal > 0 )
+            {
+                // Store parsed index
+                if ( 0 == iPos )
+                {
+                    pIndices->push_back( iVal-1 );
+                }
+                else if ( 1 == iPos )
+                {	
+                    pTexID->push_back( iVal-1 );
+                }
+                else if ( 2 == iPos )
+                {
+                    pNormalID->push_back( iVal-1 );
+                    hasNormal = true;
+                }
+                else
+                {
+                    reportErrorTokenInFace();
+                }
+            }
+            else if ( iVal < 0 )
+            {
+                // Store relatively index
+                if ( 0 == iPos )
+                {
+                    pIndices->push_back( vSize + iVal );
+                }
+                else if ( 1 == iPos )
+                {
+                    pTexID->push_back( vtSize + iVal );
+                }
+                else if ( 2 == iPos )
+                {
+                    pNormalID->push_back( vnSize + iVal );
+                    hasNormal = true;
+                }
+                else
+                {
+                    reportErrorTokenInFace();
+                }
+            }
+        }
+        pPtr += iStep;
+    }
+
+    if ( pIndices->empty() ) 
+    {
+        DefaultLogger::get()->error("Obj: Ignoring empty face");
+        m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+        return;
+    }
+
+    ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
+    
+    // Set active material, if one set
+    if (NULL != m_pModel->m_pCurrentMaterial) 
+        face->m_pMaterial = m_pModel->m_pCurrentMaterial;
+    else 
+        face->m_pMaterial = m_pModel->m_pDefaultMaterial;
+
+    // Create a default object, if nothing is there
+    if ( NULL == m_pModel->m_pCurrent )
+        createObject( "defaultobject" );
+    
+    // Assign face to mesh
+    if ( NULL == m_pModel->m_pCurrentMesh )
+    {
+        createMesh();
+    }
+    
+    // Store the face
+    m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
+    m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
+    m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); 
+    if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) 
+    {
+        m_pModel->m_pCurrentMesh->m_hasNormals = true;
+    }
+    // Skip the rest of the line
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new material description
 //	Get values for a new material description
 void ObjFileParser::getMaterialDesc()
 void ObjFileParser::getMaterialDesc()
 {
 {
-	// Each material request a new object.
-	// Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
-	// So, we create a new object only if the current on is already initialized !
-	if (m_pModel->m_pCurrent != NULL &&
-		(	m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
-			(m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0)	)
-		)
-		m_pModel->m_pCurrent = NULL;
-
-	// Get next data for material data
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
-	if (m_DataIt == m_DataItEnd)
-		return;
-
-	char *pStart = &(*m_DataIt);
+    // Each material request a new object.
+    // Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
+    // So, we create a new object only if the current on is already initialized !
+    if (m_pModel->m_pCurrent != NULL &&
+        (	m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
+            (m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0)	)
+        )
+        m_pModel->m_pCurrent = NULL;
+
+    // Get next data for material data
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    if (m_DataIt == m_DataItEnd)
+        return;
+
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
 
 
-	// Get name
-	std::string strName(pStart, &(*m_DataIt));
-	if ( strName.empty())
-		return;
-
-	// Search for material
-	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
-	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
-	{
-		// Found, using detected material
-		m_pModel->m_pCurrentMaterial = (*it).second;
-		if ( needsNewMesh( strName ))
-		{
-			createMesh();	
-		}
-		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
-	}
-
-	// Skip rest of line
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    // Get name
+    std::string strName(pStart, &(*m_DataIt));
+    if ( strName.empty())
+        return;
+
+    // Search for material
+    std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
+    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
+    {
+        // Found, using detected material
+        m_pModel->m_pCurrentMaterial = (*it).second;
+        if ( needsNewMesh( strName ))
+        {
+            createMesh();	
+        }
+        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
+    }
+
+    // Skip rest of line
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get a comment, values will be skipped
 //	Get a comment, values will be skipped
 void ObjFileParser::getComment()
 void ObjFileParser::getComment()
 {
 {
-	while (m_DataIt != m_DataItEnd)
-	{
-		if ( '\n' == (*m_DataIt))
-		{
-			++m_DataIt;
-			break;
-		}
-		else
-		{
-			++m_DataIt;
-		}
-	}
+    while (m_DataIt != m_DataItEnd)
+    {
+        if ( '\n' == (*m_DataIt))
+        {
+            ++m_DataIt;
+            break;
+        }
+        else
+        {
+            ++m_DataIt;
+        }
+    }
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get material library from file.
 //	Get material library from file.
 void ObjFileParser::getMaterialLib()
 void ObjFileParser::getMaterialLib()
 {
 {
-	// Translate tuple
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    // Translate tuple
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
     if( m_DataIt == m_DataItEnd ) {
     if( m_DataIt == m_DataItEnd ) {
         return;
         return;
     }
     }
-	
-	char *pStart = &(*m_DataIt);
+    
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
 
 
-	// Check for existence
-	const std::string strMatName(pStart, &(*m_DataIt));
-	IOStream *pFile = m_pIO->Open(strMatName);
+    // Check for existence
+    const std::string strMatName(pStart, &(*m_DataIt));
+    IOStream *pFile = m_pIO->Open(strMatName);
 
 
-	if (!pFile )
-	{
-		DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
-		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-		return;
-	}
+    if (!pFile )
+    {
+        DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
+        m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+        return;
+    }
 
 
-	// Import material library data from file
-	std::vector<char> buffer;
-	BaseImporter::TextFileToBuffer(pFile,buffer);
-	m_pIO->Close( pFile );
+    // Import material library data from file
+    std::vector<char> buffer;
+    BaseImporter::TextFileToBuffer(pFile,buffer);
+    m_pIO->Close( pFile );
 
 
-	// Importing the material library 
-	ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );			
+    // Importing the material library 
+    ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );			
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Set a new material definition as the current material.
 //	Set a new material definition as the current material.
 void ObjFileParser::getNewMaterial()
 void ObjFileParser::getNewMaterial()
 {
 {
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
-	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
     if( m_DataIt == m_DataItEnd ) {
     if( m_DataIt == m_DataItEnd ) {
         return;
         return;
     }
     }
 
 
-	char *pStart = &(*m_DataIt);
-	std::string strMat( pStart, *m_DataIt );
+    char *pStart = &(*m_DataIt);
+    std::string strMat( pStart, *m_DataIt );
     while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
-	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
-	if ( it == m_pModel->m_MaterialMap.end() )
-	{
-		// Show a warning, if material was not found
-		DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
-		m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
-	}
-	else
-	{
-		// Set new material
-		if ( needsNewMesh( strMat ) )
-		{
-			createMesh();	
-		}
-		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
-	}
-
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
+    if ( it == m_pModel->m_MaterialMap.end() )
+    {
+        // Show a warning, if material was not found
+        DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
+        m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
+    }
+    else
+    {
+        // Set new material
+        if ( needsNewMesh( strMat ) )
+        {
+            createMesh();	
+        }
+        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
+    }
+
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
 int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
 {
 {
-	int mat_index = -1;
+    int mat_index = -1;
     if( strMaterialName.empty() ) {
     if( strMaterialName.empty() ) {
         return mat_index;
         return mat_index;
     }
     }
-	for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
-	{
-		if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
-		{
-			mat_index = (int)index;
-			break;
-		}
-	}
-	return mat_index;
+    for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
+    {
+        if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
+        {
+            mat_index = (int)index;
+            break;
+        }
+    }
+    return mat_index;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Getter for a group name.  
 //	Getter for a group name.  
 void ObjFileParser::getGroupName()
 void ObjFileParser::getGroupName()
 {
 {
-	std::string strGroupName;
+    std::string strGroupName;
    
    
-	m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
+    m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
     if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
     if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
         return;
         return;
     }
     }
 
 
-	// Change active group, if necessary
-	if ( m_pModel->m_strActiveGroup != strGroupName )
-	{
-		// Search for already existing entry
-		ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
-		
-		// We are mapping groups into the object structure
-		createObject( strGroupName );
-		
-		// New group name, creating a new entry
-		if (it == m_pModel->m_Groups.end())
-		{
-			std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
-			m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
-			m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
-		}
-		else
-		{
-			m_pModel->m_pGroupFaceIDs = (*it).second;
-		}
-		m_pModel->m_strActiveGroup = strGroupName;
-	}
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    // Change active group, if necessary
+    if ( m_pModel->m_strActiveGroup != strGroupName )
+    {
+        // Search for already existing entry
+        ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
+        
+        // We are mapping groups into the object structure
+        createObject( strGroupName );
+        
+        // New group name, creating a new entry
+        if (it == m_pModel->m_Groups.end())
+        {
+            std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
+            m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
+            m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
+        }
+        else
+        {
+            m_pModel->m_pGroupFaceIDs = (*it).second;
+        }
+        m_pModel->m_strActiveGroup = strGroupName;
+    }
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Not supported
 //	Not supported
 void ObjFileParser::getGroupNumber()
 void ObjFileParser::getGroupNumber()
 {
 {
-	// Not used
+    // Not used
 
 
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Not supported
 //	Not supported
 void ObjFileParser::getGroupNumberAndResolution()
 void ObjFileParser::getGroupNumberAndResolution()
 {
 {
-	// Not used
+    // Not used
 
 
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -665,105 +665,105 @@ void ObjFileParser::getGroupNumberAndResolution()
 //	identify it.
 //	identify it.
 void ObjFileParser::getObjectName()
 void ObjFileParser::getObjectName()
 {
 {
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
     if( m_DataIt == m_DataItEnd ) {
     if( m_DataIt == m_DataItEnd ) {
         return;
         return;
     }
     }
-	char *pStart = &(*m_DataIt);
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
 
 
-	std::string strObjectName(pStart, &(*m_DataIt));
-	if (!strObjectName.empty()) 
-	{
-		// Reset current object
-		m_pModel->m_pCurrent = NULL;
-		
-		// Search for actual object
-		for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
-			it != m_pModel->m_Objects.end();
-			++it)
-		{
-			if ((*it)->m_strObjName == strObjectName)
-			{
-				m_pModel->m_pCurrent = *it;
-				break;
-			}
-		}
-
-		// Allocate a new object, if current one was not found before
+    std::string strObjectName(pStart, &(*m_DataIt));
+    if (!strObjectName.empty()) 
+    {
+        // Reset current object
+        m_pModel->m_pCurrent = NULL;
+        
+        // Search for actual object
+        for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
+            it != m_pModel->m_Objects.end();
+            ++it)
+        {
+            if ((*it)->m_strObjName == strObjectName)
+            {
+                m_pModel->m_pCurrent = *it;
+                break;
+            }
+        }
+
+        // Allocate a new object, if current one was not found before
         if( NULL == m_pModel->m_pCurrent ) {
         if( NULL == m_pModel->m_pCurrent ) {
             createObject( strObjectName );
             createObject( strObjectName );
         }
         }
-	}
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    }
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Creates a new object instance
 //	Creates a new object instance
 void ObjFileParser::createObject(const std::string &strObjectName)
 void ObjFileParser::createObject(const std::string &strObjectName)
 {
 {
-	ai_assert( NULL != m_pModel );
-	//ai_assert( !strObjectName.empty() );
-
-	m_pModel->m_pCurrent = new ObjFile::Object;
-	m_pModel->m_pCurrent->m_strObjName = strObjectName;
-	m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
-	
-	createMesh();
-
-	if( m_pModel->m_pCurrentMaterial )
-	{
-		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = 
-			getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
-		m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
-	}		
+    ai_assert( NULL != m_pModel );
+    //ai_assert( !strObjectName.empty() );
+
+    m_pModel->m_pCurrent = new ObjFile::Object;
+    m_pModel->m_pCurrent->m_strObjName = strObjectName;
+    m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
+    
+    createMesh();
+
+    if( m_pModel->m_pCurrentMaterial )
+    {
+        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = 
+            getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
+        m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
+    }		
 }
 }
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Creates a new mesh
 //	Creates a new mesh
 void ObjFileParser::createMesh()
 void ObjFileParser::createMesh()
 {
 {
-	ai_assert( NULL != m_pModel );
-	m_pModel->m_pCurrentMesh = new ObjFile::Mesh;
-	m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
-	unsigned int meshId = m_pModel->m_Meshes.size()-1;
-	if ( NULL != m_pModel->m_pCurrent )
-	{
-		m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
-	}
-	else
-	{
-		DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
-	}
+    ai_assert( NULL != m_pModel );
+    m_pModel->m_pCurrentMesh = new ObjFile::Mesh;
+    m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
+    unsigned int meshId = m_pModel->m_Meshes.size()-1;
+    if ( NULL != m_pModel->m_pCurrent )
+    {
+        m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
+    }
+    else
+    {
+        DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
+    }
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Returns true, if a new mesh must be created.
 //	Returns true, if a new mesh must be created.
 bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
 bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
 {
 {
-	if(m_pModel->m_pCurrentMesh == 0)
-	{
-		// No mesh data yet
-		return true;
-	}
-	bool newMat = false;
-	int matIdx = getMaterialIndex( rMaterialName );
-	int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
-	if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
-	{
-		// New material -> only one material per mesh, so we need to create a new 
-		// material
-		newMat = true;
-	}
-	return newMat;
+    if(m_pModel->m_pCurrentMesh == 0)
+    {
+        // No mesh data yet
+        return true;
+    }
+    bool newMat = false;
+    int matIdx = getMaterialIndex( rMaterialName );
+    int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
+    if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
+    {
+        // New material -> only one material per mesh, so we need to create a new 
+        // material
+        newMat = true;
+    }
+    return newMat;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Shows an error in parsing process.
 //	Shows an error in parsing process.
 void ObjFileParser::reportErrorTokenInFace()
 void ObjFileParser::reportErrorTokenInFace()
 {		
 {		
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-	DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------

+ 59 - 59
code/ObjFileParser.h

@@ -66,76 +66,76 @@ class IOSystem;
 class ObjFileParser
 class ObjFileParser
 {
 {
 public:
 public:
-	static const size_t BUFFERSIZE = 4096;
-	typedef std::vector<char> DataArray;
-	typedef std::vector<char>::iterator DataArrayIt;
-	typedef std::vector<char>::const_iterator ConstDataArrayIt;
+    static const size_t BUFFERSIZE = 4096;
+    typedef std::vector<char> DataArray;
+    typedef std::vector<char>::iterator DataArrayIt;
+    typedef std::vector<char>::const_iterator ConstDataArrayIt;
 
 
 public:
 public:
-	///	\brief	Constructor with data array.
-	ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem* io);
-	///	\brief	Destructor
-	~ObjFileParser();
-	///	\brief	Model getter.
-	ObjFile::Model *GetModel() const;
+    ///	\brief	Constructor with data array.
+    ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem* io);
+    ///	\brief	Destructor
+    ~ObjFileParser();
+    ///	\brief	Model getter.
+    ObjFile::Model *GetModel() const;
 
 
 private:
 private:
-	///	Parse the loaded file
-	void parseFile();
-	///	Method to copy the new delimited word in the current line.
-	void copyNextWord(char *pBuffer, size_t length);
-	///	Method to copy the new line.
-	void copyNextLine(char *pBuffer, size_t length);
+    ///	Parse the loaded file
+    void parseFile();
+    ///	Method to copy the new delimited word in the current line.
+    void copyNextWord(char *pBuffer, size_t length);
+    ///	Method to copy the new line.
+    void copyNextLine(char *pBuffer, size_t length);
     /// Stores the vector 
     /// Stores the vector 
     void getVector( std::vector<aiVector3D> &point3d_array );
     void getVector( std::vector<aiVector3D> &point3d_array );
     ///	Stores the following 3d vector.
     ///	Stores the following 3d vector.
-	void getVector3( std::vector<aiVector3D> &point3d_array );
-	///	Stores the following 3d vector.
-	void getVector2(std::vector<aiVector2D> &point2d_array);
+    void getVector3( std::vector<aiVector3D> &point3d_array );
+    ///	Stores the following 3d vector.
+    void getVector2(std::vector<aiVector2D> &point2d_array);
     ///	Stores the following face.
     ///	Stores the following face.
-	void getFace(aiPrimitiveType type);
-	/// Reads the material description.
+    void getFace(aiPrimitiveType type);
+    /// Reads the material description.
     void getMaterialDesc();
     void getMaterialDesc();
-	///	Gets a comment.
-	void getComment();
-	/// Gets a a material library.
-	void getMaterialLib();
-	/// Creates a new material.
-	void getNewMaterial();
-	/// Gets the group name from file.
-	void getGroupName();
-	/// Gets the group number from file.
-	void getGroupNumber();
-	/// Gets the group number and resolution from file.
-	void getGroupNumberAndResolution();
-	/// Returns the index of the material. Is -1 if not material was found.
-	int getMaterialIndex( const std::string &strMaterialName );
-	/// Parse object name
-	void getObjectName();
-	/// Creates a new object.
-	void createObject(const std::string &strObjectName);
-	///	Creates a new mesh.
-	void createMesh(); 
-	///	Returns true, if a new mesh instance must be created.
-	bool needsNewMesh( const std::string &rMaterialName );
-	///	Error report in token
-	void reportErrorTokenInFace();
+    ///	Gets a comment.
+    void getComment();
+    /// Gets a a material library.
+    void getMaterialLib();
+    /// Creates a new material.
+    void getNewMaterial();
+    /// Gets the group name from file.
+    void getGroupName();
+    /// Gets the group number from file.
+    void getGroupNumber();
+    /// Gets the group number and resolution from file.
+    void getGroupNumberAndResolution();
+    /// Returns the index of the material. Is -1 if not material was found.
+    int getMaterialIndex( const std::string &strMaterialName );
+    /// Parse object name
+    void getObjectName();
+    /// Creates a new object.
+    void createObject(const std::string &strObjectName);
+    ///	Creates a new mesh.
+    void createMesh(); 
+    ///	Returns true, if a new mesh instance must be created.
+    bool needsNewMesh( const std::string &rMaterialName );
+    ///	Error report in token
+    void reportErrorTokenInFace();
 
 
 private:
 private:
-	///	Default material name
-	static const std::string DEFAULT_MATERIAL;
-	//!	Iterator to current position in buffer
-	DataArrayIt m_DataIt;
-	//!	Iterator to end position of buffer
-	DataArrayIt m_DataItEnd;
-	//!	Pointer to model instance
-	ObjFile::Model *m_pModel;
-	//!	Current line (for debugging)
-	unsigned int m_uiLine;
-	//!	Helper buffer
-	char m_buffer[BUFFERSIZE];
-	///	Pointer to IO system instance.
-	IOSystem *m_pIO;
+    ///	Default material name
+    static const std::string DEFAULT_MATERIAL;
+    //!	Iterator to current position in buffer
+    DataArrayIt m_DataIt;
+    //!	Iterator to end position of buffer
+    DataArrayIt m_DataItEnd;
+    //!	Pointer to model instance
+    ObjFile::Model *m_pModel;
+    //!	Current line (for debugging)
+    unsigned int m_uiLine;
+    //!	Helper buffer
+    char m_buffer[BUFFERSIZE];
+    ///	Pointer to IO system instance.
+    IOSystem *m_pIO;
 };
 };
 
 
 }	// Namespace Assimp
 }	// Namespace Assimp

+ 866 - 0
code/OpenGEXImporter.cpp

@@ -0,0 +1,866 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#include "AssimpPCH.h"
+#include "OpenGEXImporter.h"
+#include "DefaultIOSystem.h"
+#include "MakeVerboseFormat.h"
+
+#include <openddlparser/OpenDDLParser.h>
+
+#include <vector>
+
+static const aiImporterDesc desc = {
+    "Open Game Engine Exchange",
+    "",
+    "",
+    "",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "ogex"
+};
+
+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 char *TextureType         = "Texture";
+
+    enum TokenType {
+        NoneType = -1,
+        MetricToken,
+        NameToken,
+        ObjectRefToken,
+        MaterialRefToken,
+        MetricKeyToken,
+        GeometryNodeToken,
+        GeometryObjectToken,
+        TransformToken,
+        MeshToken,
+        VertexArrayToken,
+        IndexArrayToken,
+        MaterialToken,
+        ColorToken,
+        TextureToken
+    };
+
+    static const char *ValidMetricToken[ 4 ] = {
+        Metric_DistanceType,
+        Metric_AngleType,
+        Metric_TimeType,
+        Metric_UpType
+    };
+
+    static int isValidMetricType( const char *token ) {
+        if( NULL == token ) {
+            return false;
+        }
+
+        int idx( -1 );
+        for( size_t i = 0; i < 4; i++ ) {
+            if( 0 == strncmp( ValidMetricToken[ i ], token, strlen( token ) ) ) {
+                idx = (int) i;
+                break;
+            }
+        }
+
+        return idx;
+    }
+
+    static TokenType matchTokenType( const char *tokenType ) {
+        if( 0 == strncmp( MetricType, tokenType, strlen( MetricType ) ) ) {
+            return MetricToken;
+        } else if( 0 == strncmp( NameType, tokenType, strlen( NameType ) ) ) {
+            return NameToken;
+        }
+        else if( 0 == strncmp( ObjectRefType, tokenType, strlen( ObjectRefType ) ) ) {
+            return ObjectRefToken;
+        }
+        else if( 0 == strncmp( MaterialRefType, tokenType, strlen( MaterialRefType ) ) ) {
+            return MaterialRefToken; 
+        }
+        else if( 0 == strncmp( MetricKeyType, tokenType, strlen( MetricKeyType ) ) ) {
+            return MetricKeyToken;
+        }
+        else if( 0 == strncmp( GeometryNodeType, tokenType, strlen( GeometryNodeType ) ) ) {
+            return GeometryNodeToken;
+        }
+        else if( 0 == strncmp( GeometryObjectType, tokenType, strlen( GeometryObjectType ) ) ) {
+            return GeometryObjectToken;
+        }
+        else if( 0 == strncmp( TransformType, tokenType, strlen( TransformType ) ) ) {
+            return TransformToken;
+        }
+        else if( 0 == strncmp( MeshType, tokenType, strlen( MeshType ) ) ) {
+            return MeshToken;
+        }
+        else if( 0 == strncmp( VertexArrayType, tokenType, strlen( VertexArrayType ) ) ) {
+            return VertexArrayToken;
+        }
+        else if( 0 == strncmp( IndexArrayType, tokenType, strlen( IndexArrayType ) ) ) {
+            return IndexArrayToken;
+        }
+        else if( 0 == strncmp( MaterialType, tokenType, strlen( MaterialType ) ) ) {
+            return MaterialToken;
+        }
+        else if( 0 == strncmp( ColorType, tokenType, strlen( ColorType ) ) ) {
+            return ColorToken;
+        }
+        else if( 0 == strncmp( TextureType, tokenType, strlen( TextureType ) ) ) {
+            return TextureToken;
+        }
+
+        return NoneType;
+    }
+
+} // Namespace Grammar
+
+namespace Assimp {
+namespace OpenGEX {
+
+USE_ODDLPARSER_NS
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::VertexContainer::VertexContainer()
+: m_numVerts( 0 )
+, m_vertices()
+, m_numNormals( 0 )
+, m_normals()
+, m_textureCoords()
+, m_numUVComps() {
+    // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::VertexContainer::~VertexContainer() {
+    delete[] m_vertices;
+    delete[] m_normals;
+    for( size_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++ ) {
+        delete [] m_textureCoords[ i ];
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::RefInfo::RefInfo( aiNode *node, Type type, std::vector<std::string> &names )
+: m_node( node )
+, m_type( type )
+, m_Names( names ) {
+    // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::RefInfo::~RefInfo() {
+    // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::OpenGEXImporter() 
+: m_meshCache()
+, m_root( NULL )
+, m_nodeChildMap()
+, m_mesh2refMap()
+, m_ctx( NULL )
+, m_currentNode( NULL )
+, m_currentMesh( NULL )
+, m_nodeStack()
+, m_unresolvedRefStack() {
+    // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::~OpenGEXImporter() {
+    m_ctx = NULL;
+}
+
+//------------------------------------------------------------------------------------------------
+bool OpenGEXImporter::CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const {
+    bool canRead( false );
+    if( !checkSig ) {
+        canRead = SimpleExtensionCheck( file, "ogex" );
+    } else {
+        static const char *token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
+        canRead = BaseImporter::SearchFileHeaderForToken( pIOHandler, file, token, 4 );
+    }
+
+    return canRead;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) {
+    // open source file
+    IOStream *file = pIOHandler->Open( filename, "rb" );
+    if( !file ) {
+        throw DeadlyImportError( "Failed to open file " + filename );
+    }
+
+    std::vector<char> buffer;
+    TextFileToBuffer( file, buffer );
+
+    OpenDDLParser myParser;
+    myParser.setBuffer( &buffer[ 0 ], buffer.size() );
+    bool success( myParser.parse() );
+    if( success ) {
+        m_ctx = myParser.getContext();
+        pScene->mRootNode = new aiNode;
+        pScene->mRootNode->mName.Set( filename );
+        handleNodes( m_ctx->m_root, pScene );
+    }
+
+    copyMeshes( pScene );
+    resolveReferences();
+    createNodeTree( pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+const aiImporterDesc *OpenGEXImporter::GetInfo() const {
+    return &desc;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::SetupProperties( const Importer *pImp ) {
+    if( NULL == pImp ) {
+        return;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleNodes( DDLNode *node, aiScene *pScene ) {
+    if( NULL == node ) {
+        return;
+    }
+
+    DDLNode::DllNodeList childs = node->getChildNodeList();
+    for( DDLNode::DllNodeList::iterator it = childs.begin(); it != childs.end(); it++ ) {
+        Grammar::TokenType tokenType( Grammar::matchTokenType( ( *it )->getType().c_str() ) );
+        switch( tokenType ) {
+            case Grammar::MetricToken:
+                handleMetricNode( *it, pScene );
+                break;
+
+            case Grammar::NameToken:
+                handleNameNode( *it, pScene );
+                break;
+
+            case Grammar::ObjectRefToken:
+                handleObjectRefNode( *it, pScene );
+                break;
+
+            case Grammar::MaterialRefToken:
+                handleMaterialRefNode( *it, pScene );
+                break;
+
+            case Grammar::MetricKeyToken:
+                break;
+
+            case Grammar::GeometryNodeToken:
+                handleGeometryNode( *it, pScene );
+                break;
+
+            case Grammar::GeometryObjectToken:
+                handleGeometryObject( *it, pScene );
+                break;
+
+            case Grammar::TransformToken:
+                handleTransformNode( *it, pScene );
+                break;
+
+            case Grammar::MeshToken:
+                handleMeshNode( *it, pScene );
+                break;
+
+            case Grammar::VertexArrayToken:
+                handleVertexArrayNode( *it, pScene );
+                break;
+
+            case Grammar::IndexArrayToken:
+                handleIndexArrayNode( *it, pScene );
+                break;
+
+            case Grammar::MaterialToken:
+                handleMaterialNode( *it, pScene );
+                break;
+
+            case Grammar::ColorToken:
+                handleColorNode( *it, pScene );
+                break;
+
+            case Grammar::TextureToken:
+                handleTextureNode( *it, pScene );
+                break;
+            
+            default:
+                break;
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene *pScene ) {
+    if( NULL == node || NULL == m_ctx ) {
+        return;
+    }
+
+    if( m_ctx->m_root != node->getParent() ) {
+        return;
+    }
+
+    Property *prop( node->getProperties() );
+    while( NULL != prop ) {
+        if( NULL != prop->m_id ) {
+            if( Value::ddl_string == prop->m_primData->m_type ) {
+                std::string valName( (char*) prop->m_primData->m_data );
+                int type( Grammar::isValidMetricType( valName.c_str() ) );
+                if( Grammar::NoneType != type ) {
+                    Value *val( node->getValue() );
+                    if( NULL != val ) {
+                        if( Value::ddl_float == val->m_type ) {
+                            m_metrics[ type ].m_floatValue = val->getFloat();
+                        } else if( Value::ddl_int32 == val->m_type ) {
+                            m_metrics[ type ].m_intValue = val->getInt32();
+                        } else if( Value::ddl_string == val->m_type ) {
+                            m_metrics[type].m_stringValue = std::string( val->getString() );
+                        } else {
+                            throw DeadlyImportError( "OpenGEX: invalid data type for Metric node." );
+                        }
+                    }
+                }
+            }
+        }
+        prop = prop->m_next;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    Value *val( node->getValue() );
+    if( NULL != val ) {
+        if( Value::ddl_string != val->m_type ) {
+            throw DeadlyImportError( "OpenGEX: invalid data type for value in node name." );
+            return;
+        }
+
+        const std::string name( val->getString() );
+        m_currentNode->mName.Set( name.c_str() );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+static void getRefNames( DDLNode *node, std::vector<std::string> &names ) {
+    ai_assert( NULL != node );
+
+    Reference *ref = node->getReferences();
+    if( NULL != ref ) {
+        for( size_t i = 0; i < ref->m_numRefs; i++ )  {
+            Name *currentName( ref->m_referencedName[ i ] );
+            if( NULL != currentName && NULL != currentName->m_id ) {
+                const std::string name( currentName->m_id->m_buffer );
+                if( !name.empty() ) {
+                    names.push_back( name );
+                }
+            }
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    std::vector<std::string> objRefNames;
+    getRefNames( node, objRefNames );
+    m_currentNode->mNumMeshes = objRefNames.size();
+    m_currentNode->mMeshes = new unsigned int[ objRefNames.size() ];
+    if( !objRefNames.empty() ) {
+        m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    std::vector<std::string> matRefNames;
+    getRefNames( node, matRefNames );
+    if( !matRefNames.empty() ) {
+        m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleGeometryNode( DDLNode *node, aiScene *pScene ) {
+    aiNode *newNode = new aiNode;
+    pushNode( newNode, pScene );
+    m_currentNode = newNode;
+    handleNodes( node, pScene );
+    
+    popNode();
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleGeometryObject( DDLNode *node, aiScene *pScene ) {
+    handleNodes( node, pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+static void setMatrix( aiNode *node, DataArrayList *transformData ) {
+    ai_assert( NULL != node );
+    ai_assert( NULL != transformData );
+
+    float m[ 16 ];
+    size_t i( 1 );
+    Value *next( transformData->m_dataList->m_next );
+    m[ 0 ] = transformData->m_dataList->getFloat();
+    while(  next != NULL ) {
+        m[ i ] = next->getFloat();
+        next = next->m_next;
+        i++;
+    }
+    
+    node->mTransformation.a1 = m[ 0 ];
+    node->mTransformation.a2 = m[ 1 ];
+    node->mTransformation.a3 = m[ 2 ];
+    node->mTransformation.a4 = m[ 3 ];
+
+    node->mTransformation.b1 = m[ 4 ];
+    node->mTransformation.b2 = m[ 5 ];
+    node->mTransformation.b3 = m[ 6 ];
+    node->mTransformation.b4 = m[ 7 ];
+
+    node->mTransformation.c1 = m[ 8 ];
+    node->mTransformation.c2 = m[ 9 ];
+    node->mTransformation.c3 = m[ 10 ];
+    node->mTransformation.c4 = m[ 11 ];
+
+    node->mTransformation.d1 = m[ 12 ];
+    node->mTransformation.d2 = m[ 13 ];
+    node->mTransformation.d3 = m[ 14 ];
+    node->mTransformation.d4 = m[ 15 ];
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+
+    DataArrayList *transformData( node->getDataArrayList() );
+    if( NULL != transformData ) {
+        if( transformData->m_numItems != 16 ) {
+            throw DeadlyImportError( "Invalid number of data for transform matrix." );
+            return;
+        }
+        setMatrix( m_currentNode, transformData );
+    } 
+}
+
+//------------------------------------------------------------------------------------------------
+static void propId2StdString( Property *prop, std::string &name, std::string &key ) {
+    name = key = "";
+    if( NULL == prop ) {
+        return;
+    }
+
+    if( NULL != prop->m_id ) {
+        name = prop->m_id->m_buffer;
+        if( Value::ddl_string == prop->m_primData->m_type ) {
+            key = prop->m_primData->getString();
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    m_currentMesh = new aiMesh;
+    const size_t meshidx( m_meshCache.size() );
+    m_meshCache.push_back( m_currentMesh );
+    
+    Property *prop = node->getProperties();
+    if( NULL != prop ) {
+        std::string propName, propKey;
+        propId2StdString( prop, propName, propKey );
+        if( "primitive" == propName ) {
+            if( "triangles" == propKey ) {
+                m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+            }
+        }
+    }
+
+    handleNodes( node, pScene );
+
+    DDLNode *parent( node->getParent() );
+    if( NULL != parent ) {
+        const std::string &name = parent->getName();
+        m_mesh2refMap[ name ] = meshidx;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+enum MeshAttribute {
+    None,
+    Position,
+    Normal,
+    TexCoord
+};
+
+//------------------------------------------------------------------------------------------------
+static MeshAttribute getAttributeByName( const char *attribName ) {
+    ai_assert( NULL != attribName  );
+
+    if( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) {
+        return Position;
+    } else if( 0 == strncmp( "normal", attribName, strlen( "normal" ) ) ) {
+        return Normal;
+    } else if( 0 == strncmp( "texcoord", attribName, strlen( "texcoord" ) ) ) {
+        return TexCoord;
+    }
+
+    return None;
+}
+
+//------------------------------------------------------------------------------------------------
+static void fillVector3( aiVector3D *vec3, Value *vals ) {
+    ai_assert( NULL != vec3 );
+    ai_assert( NULL != vals );
+
+    float x( 0.0f ), y( 0.0f ), z( 0.0f );
+    Value *next( vals );
+    x = next->getFloat();
+    next = next->m_next;
+    y = next->getFloat();
+    next = next->m_next;
+    if( NULL != next ) {
+        z = next->getFloat();
+    }
+
+    vec3->Set( x, y, z );
+}
+
+//------------------------------------------------------------------------------------------------
+static size_t countDataArrayListItems( DataArrayList *vaList ) {
+    size_t numItems( 0 );
+    if( NULL == vaList ) {
+        return numItems;
+    }
+
+    DataArrayList *next( vaList );
+    while( NULL != next ) {
+        if( NULL != vaList->m_dataList ) {
+            numItems++;
+        }
+        next = next->m_next;
+    }
+
+    return numItems;
+}
+
+//------------------------------------------------------------------------------------------------
+static void copyVectorArray( size_t numItems, DataArrayList *vaList, aiVector3D *vectorArray ) {
+    for( size_t i = 0; i < numItems; i++ ) {
+        Value *next( vaList->m_dataList );
+        fillVector3( &vectorArray[ i ], next );
+        vaList = vaList->m_next;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    if( NULL == node ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    Property *prop( node->getProperties() );
+    if( NULL != prop ) {
+        std::string propName, propKey;
+        propId2StdString( prop, propName, propKey );
+        MeshAttribute attribType( getAttributeByName( propKey.c_str() ) );
+        if( None == attribType ) {
+            return;
+        }
+
+        DataArrayList *vaList = node->getDataArrayList();
+        if( NULL == vaList ) {
+            return;
+        }
+
+        const size_t numItems( countDataArrayListItems( vaList ) );
+        Value *next( vaList->m_dataList );
+        if( Position == attribType ) {
+            m_currentVertices.m_numVerts = numItems;
+            m_currentVertices.m_vertices = new aiVector3D[ numItems ];
+            copyVectorArray( numItems, vaList, m_currentVertices.m_vertices );
+        } else if( Normal == attribType ) {
+            m_currentVertices.m_numNormals = numItems;
+            m_currentVertices.m_normals = new aiVector3D[ numItems ];
+            copyVectorArray( numItems, vaList, m_currentVertices.m_normals );
+        } else if( TexCoord == attribType ) {
+            m_currentVertices.m_numUVComps[ 0 ] = numItems;
+            m_currentVertices.m_textureCoords[ 0 ] = new aiVector3D[ numItems ];
+            copyVectorArray( numItems, vaList, m_currentVertices.m_textureCoords[ 0 ] );
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    if( NULL == node ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    if( NULL == m_currentMesh ) {
+        throw DeadlyImportError( "No current mesh for index data found." );
+        return;
+    }
+
+    DataArrayList *vaList = node->getDataArrayList();
+    if( NULL == vaList ) {
+        return;
+    }
+
+    const size_t numItems( countDataArrayListItems( vaList ) );
+    m_currentMesh->mNumFaces = numItems;
+    m_currentMesh->mFaces = new aiFace[ numItems ];
+    m_currentMesh->mNumVertices = numItems * 3;
+    m_currentMesh->mVertices = new aiVector3D[ m_currentMesh->mNumVertices ];
+    m_currentMesh->mNormals = new aiVector3D[ m_currentMesh->mNumVertices ];
+    m_currentMesh->mNumUVComponents[ 0 ] = numItems * 3;
+    m_currentMesh->mTextureCoords[ 0 ] = new aiVector3D[ m_currentMesh->mNumUVComponents[ 0 ] ];
+
+    unsigned int index( 0 );
+    for( size_t i = 0; i < m_currentMesh->mNumFaces; i++ ) {
+        aiFace &current(  m_currentMesh->mFaces[ i ] );
+        current.mNumIndices = 3;
+        current.mIndices = new unsigned int[ current.mNumIndices ];
+        Value *next( vaList->m_dataList );
+        for( size_t indices = 0; indices < current.mNumIndices; indices++ ) {
+            const int idx = next->getInt32();
+            ai_assert( idx <= m_currentVertices.m_numVerts );
+
+            aiVector3D &pos = ( m_currentVertices.m_vertices[ idx ] );
+            aiVector3D &normal = ( m_currentVertices.m_normals[ idx ] );
+            aiVector3D &tex = ( m_currentVertices.m_textureCoords[ 0 ][ idx ] );
+
+            ai_assert( index < m_currentMesh->mNumVertices );
+            m_currentMesh->mVertices[ index ].Set( pos.x, pos.y, pos.z );
+            m_currentMesh->mNormals[ index ].Set( normal.x, normal.y, normal.z );
+            m_currentMesh->mTextureCoords[0][ index ].Set( tex.x, tex.y, tex.z );
+            current.mIndices[ indices ] = index;
+            index++;
+            
+            next = next->m_next;
+        }
+        vaList = vaList->m_next;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::copyMeshes( aiScene *pScene ) {
+    if( m_meshCache.empty() ) {
+        return;
+    }
+    pScene->mNumMeshes = m_meshCache.size();
+    pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
+    size_t i( 0 );
+    for( std::vector<aiMesh*>::iterator it = m_meshCache.begin(); it != m_meshCache.end(); it++ ) {
+        pScene->mMeshes[ i ] = *it;
+        i++;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::resolveReferences() {
+    if( m_unresolvedRefStack.empty() ) {
+        return;
+    }
+
+    RefInfo *currentRefInfo( NULL );
+    for( std::vector<RefInfo*>::iterator it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) {
+        currentRefInfo = *it;
+        if( NULL != currentRefInfo ) {
+            aiNode *node( currentRefInfo->m_node );
+            if( RefInfo::MeshRef == currentRefInfo->m_type ) {
+                for( size_t i = 0; i < currentRefInfo->m_Names.size(); i++ ) {
+                    const std::string &name(currentRefInfo->m_Names[ i ] );
+                    ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) );
+                    if( m_mesh2refMap.end() != it ) {
+                        unsigned int meshIdx = m_mesh2refMap[ name ];
+                        node->mMeshes[ i ] = meshIdx;
+                    }
+                }
+            } else if( RefInfo::MaterialRef == currentRefInfo->m_type ) {
+                // ToDo!
+            } else {
+                throw DeadlyImportError( "Unknown reference info to resolve." );
+            }
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::createNodeTree( aiScene *pScene ) {
+    if( NULL == m_root ) {
+        return;
+    }
+
+    if( m_root->m_children.empty() ) {
+        return;
+    }
+    size_t i( 0 );
+    pScene->mRootNode->mNumChildren = m_root->m_children.size();
+    pScene->mRootNode->mChildren = new C_STRUCT aiNode*[ pScene->mRootNode->mNumChildren ];
+    for( ChildInfo::NodeList::iterator it = m_root->m_children.begin(); it != m_root->m_children.end(); it++ ) {
+        pScene->mRootNode->mChildren[ i ] = *it;
+        i++;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
+    ai_assert( NULL != pScene );
+
+    if( NULL != node ) {
+        ChildInfo *info( NULL );
+        if( m_nodeStack.empty() ) {
+            node->mParent = pScene->mRootNode;
+            NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) );
+            if( m_nodeChildMap.end() == it ) {
+                info = new ChildInfo;
+                m_root = info;
+                m_nodeChildMap[ node->mParent ] = info;
+            } else {
+                info = it->second;
+            }
+            info->m_children.push_back( node );
+        } else {
+            aiNode *parent( m_nodeStack.back() );
+            ai_assert( NULL != parent );
+            node->mParent = parent;
+            NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) );
+            if( m_nodeChildMap.end() == it ) {
+                info = new ChildInfo;
+                m_nodeChildMap[ node->mParent ] = info;
+            } else {
+                info = it->second;
+            }
+            info->m_children.push_back( node );
+        }
+        m_nodeStack.push_back( node );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+aiNode *OpenGEXImporter::popNode() {
+    if( m_nodeStack.empty() ) {
+        return NULL;
+    }
+    
+    aiNode *node( top() );
+    m_nodeStack.pop_back();
+    
+    return node;
+}
+
+//------------------------------------------------------------------------------------------------
+aiNode *OpenGEXImporter::top() const {
+    if( m_nodeStack.empty() ) {
+        return NULL;
+    }
+
+    return m_nodeStack.back();
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::clearNodeStack() {
+    m_nodeStack.clear();
+}
+
+//------------------------------------------------------------------------------------------------
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER

+ 186 - 0
code/OpenGEXImporter.h

@@ -0,0 +1,186 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_OPENGEX_IMPORTER_H
+#define AI_OPENGEX_IMPORTER_H
+
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#include "BaseImporter.h"
+
+#include <vector>
+
+namespace ODDLParser {
+    class DDLNode;
+    struct Context;
+}
+
+namespace Assimp {
+namespace OpenGEX {
+
+struct MetricInfo {
+    enum Type {
+        Distance = 0,
+        Angle,
+        Time,
+        Up,
+        Max
+    };
+
+    std::string m_stringValue;
+    float m_floatValue;
+    int m_intValue;
+
+    MetricInfo()
+    : m_stringValue( "" )
+    , m_floatValue( 0.0f )
+    , m_intValue( -1 ) {
+        // empty
+    }
+};
+
+/** @brief  This class is used to implement the OpenGEX importer
+ *
+ *  See http://opengex.org/OpenGEX.pdf for spec.
+ */
+class OpenGEXImporter : public BaseImporter {
+public:
+    /// The class constructor.
+    OpenGEXImporter();
+
+    /// The class destructor.
+    virtual ~OpenGEXImporter();
+
+    /// BaseImporter override.
+    virtual bool CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const;
+
+    /// BaseImporter override.
+    virtual void InternReadFile( const std::string &file, aiScene *pScene, IOSystem *pIOHandler );
+
+    /// BaseImporter override.
+    virtual const aiImporterDesc *GetInfo() const;
+
+    /// BaseImporter override.
+    virtual void SetupProperties( const Importer *pImp );
+
+protected:
+    void handleNodes( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMetricNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleNameNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleObjectRefNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleGeometryNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleGeometryObject( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void copyMeshes( aiScene *pScene );
+    void resolveReferences();
+    void pushNode( aiNode *node, aiScene *pScene );
+    aiNode *popNode();
+    aiNode *top() const;
+    void clearNodeStack();
+    void createNodeTree( aiScene *pScene );
+
+private:
+    struct VertexContainer {
+        size_t m_numVerts;
+        aiVector3D *m_vertices;
+        size_t m_numNormals;
+        aiVector3D *m_normals;
+        size_t m_numUVComps[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+        aiVector3D *m_textureCoords[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+
+        VertexContainer();
+        ~VertexContainer();
+
+    private:
+        VertexContainer( const VertexContainer & );
+        VertexContainer &operator = ( const VertexContainer & );
+    };
+
+    struct RefInfo {
+        enum Type {
+            MeshRef,
+            MaterialRef
+        };
+
+        aiNode *m_node;
+        Type m_type;
+        std::vector<std::string> m_Names;
+
+        RefInfo( aiNode *node, Type type, std::vector<std::string> &names );
+        ~RefInfo();
+
+    private:
+        RefInfo( const RefInfo & );
+        RefInfo &operator = ( const RefInfo & );
+    };
+
+    struct ChildInfo {
+        typedef std::list<aiNode*> NodeList;
+        std::list<aiNode*> m_children;
+    };
+    ChildInfo *m_root;
+    typedef std::map<aiNode*, ChildInfo*> NodeChildMap;
+    NodeChildMap m_nodeChildMap;
+
+    std::vector<aiMesh*> m_meshCache;
+    typedef std::map<std::string, size_t> ReferenceMap;
+    std::map<std::string, size_t> m_mesh2refMap;
+
+    ODDLParser::Context *m_ctx;
+    MetricInfo m_metrics[ MetricInfo::Max ];
+    aiNode *m_currentNode;
+    VertexContainer m_currentVertices;
+    aiMesh *m_currentMesh;
+    std::vector<aiNode*> m_nodeStack;
+    std::vector<RefInfo*> m_unresolvedRefStack;
+};
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#endif // AI_OPENGEX_IMPORTER_H

+ 265 - 0
code/OpenGEXStructs.h

@@ -0,0 +1,265 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_OPENGEXSTRUCTS_H_INC
+#define AI_OPENGEXSTRUCTS_H_INC
+
+#include <string>
+#include <map>
+
+namespace Assimp {
+namespace OpenGEX {
+
+struct Skin;
+struct Object;
+struct LightObject;
+struct CameraObject;
+struct Material;
+struct BoneNode;
+struct BoneCountArray;
+struct BoneIndexArray;
+struct BoneWeightArray;
+
+struct Metric {
+    float m_distance;
+    float m_angle;
+    float m_time;
+    float m_up;
+};
+
+struct VertexArray {
+    std::string arrayAttrib;
+    unsigned int morphIndex;
+};
+
+struct IndexArray {
+    unsigned int materialIndex;
+    unsigned int restartIndex;
+    std::string frontFace;
+};
+
+struct Mesh {
+    unsigned int meshLevel;
+    std::string meshPrimitive;
+    Skin *skinStructure;
+};
+
+struct Node {
+    std::string nodeName;
+};
+
+struct GeometryNode {
+    bool visibleFlag[ 2 ];
+    bool shadowFlag[ 2 ];
+    bool motionBlurFlag[ 2 ];
+};
+
+struct LightNode {
+    bool shadowFlag[ 2 ];
+    const LightObject *lightObjectStructure;
+};
+
+struct CameraNode {
+    const CameraObject *cameraObjectStructure;
+};
+
+struct GeometryObject {
+    Object *object;
+    bool visibleFlag;
+    bool shadowFlag;
+    bool motionBlurFlag;
+    std::map<std::string, Mesh*> meshMap;
+};
+
+struct LightObject {
+    Object *object;
+    std::string typeString;
+    bool shadowFlag;
+};
+
+
+struct CameraObject {
+    float focalLength;
+    float nearDepth;
+    float farDepth;
+};
+
+struct Matrix {
+    bool objectFlag;
+};
+
+struct Transform {
+    Matrix *matrix;
+    int transformCount;
+    const float	*transformArray;
+};
+
+struct Translation {
+    std::string translationKind;
+};
+
+struct Rotation {
+    std::string rotationKind;
+};
+
+struct Scale {
+    std::string scaleKind;
+};
+
+struct Name {
+    std::string	name;
+};
+
+
+struct ObjectRef {
+    Object *targetStructure;
+};
+
+struct MaterialRef {
+    unsigned int materialIndex;
+    const Material *targetStructure;
+};
+
+struct BoneRefArray {
+    int	boneCount;
+    const BoneNode **boneNodeArray;
+};
+
+struct BoneCount {
+    int	vertexCount;
+    const unsigned short *boneCountArray;
+    unsigned short *arrayStorage;
+};
+
+struct BoneIndex {
+    int	boneIndexCount;
+    const unsigned short *boneIndexArray;
+    unsigned short *arrayStorage;
+};
+
+
+struct BoneWeight {
+    int boneWeightCount;
+    const float *boneWeightArray;
+};
+
+struct Skeleton {
+    const BoneRefArray *boneRefArrayStructure;
+    const Transform *transformStructure;
+};
+
+struct Skin {
+    const Skeleton *skeletonStructure;
+    const BoneCountArray *boneCountArrayStructure;
+    const BoneIndexArray *boneIndexArrayStructure;
+    const BoneWeightArray *boneWeightArrayStructure;
+};
+
+struct Material {
+    bool twoSidedFlag;
+    const char *materialName;
+};
+
+struct Attrib {
+    std::string attribString;
+};
+
+struct Param {
+    float param;
+};
+
+struct Color {
+    float color[ 4 ];
+};
+
+struct Texture {
+    std::string textureName;
+    unsigned int texcoordIndex;
+};
+
+struct Atten {
+    std::string attenKind;
+    std::string curveType;
+
+    float beginParam;
+    float endParam;
+
+    float scaleParam;
+    float offsetParam;
+
+    float constantParam;
+    float linearParam;
+    float quadraticParam;
+
+    float powerParam;
+};
+
+struct Key {
+    std::string keyKind;
+    bool scalarFlag;
+};
+
+struct Curve {
+    std::string curveType;
+    const Key *keyValueStructure;
+    const Key *keyControlStructure[ 2 ];
+    const Key *keyTensionStructure;
+    const Key *keyContinuityStructure;
+    const Key *keyBiasStructure;
+};
+
+struct Animation {
+    int clipIndex;
+    bool beginFlag;
+    bool endFlag;
+    float beginTime;
+    float endTime;
+};
+
+struct OpenGexDataDescription {
+    float distanceScale;
+    float angleScale;
+    float timeScale;
+    int upDirection;
+};
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // AI_OPENGEXSTRUCTS_H_INC

+ 6 - 1
code/ParsingUtils.h

@@ -202,7 +202,12 @@ template <class char_t>
 AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
 AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
 {
 {
 	if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
 	if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
-		in += len+1;
+		if (in[len] != '\0') {
+			in += len+1;
+		} else {
+			// If EOF after the token make sure we don't go past end of buffer
+			in += len;
+		}
 		return true;
 		return true;
 	}
 	}
 
 

+ 2 - 2
code/PlyExporter.cpp

@@ -55,7 +55,7 @@ namespace Assimp	{
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp
-void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	PlyExporter exporter(pFile, pScene);
 	PlyExporter exporter(pFile, pScene);
@@ -69,7 +69,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
 	outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
 	outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
 }
 }
 
 
-void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	PlyExporter exporter(pFile, pScene, true);
 	PlyExporter exporter(pFile, pScene, true);

+ 46 - 27
code/PlyLoader.cpp

@@ -68,6 +68,25 @@ static const aiImporterDesc desc = {
 	"ply" 
 	"ply" 
 };
 };
 
 
+
+// ------------------------------------------------------------------------------------------------
+// Internal stuff
+namespace
+{
+	// ------------------------------------------------------------------------------------------------
+	// Checks that property index is within range
+	template <class T>
+	const T &GetProperty(const std::vector<T> &props, int idx)
+	{
+        if( static_cast< size_t >( idx ) >= props.size() ) {
+            throw DeadlyImportError( "Invalid .ply file: Property index is out of range." );
+        }
+
+		return props[idx];
+	}
+}
+
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 PLYImporter::PLYImporter()
 PLYImporter::PLYImporter()
@@ -435,13 +454,13 @@ void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
 			if (0xFFFFFFFF != aiPositions[0])
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 			{
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
+					GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[1])
 			if (0xFFFFFFFF != aiPositions[1])
 			{
 			{
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
+					GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
 			}
 			}
 			// and add them to our nice list
 			// and add them to our nice list
 			pvOut->push_back(vOut);
 			pvOut->push_back(vOut);
@@ -545,19 +564,19 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 			if (0xFFFFFFFF != aiPositions[0])
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 			{
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
+					GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[1])
 			if (0xFFFFFFFF != aiPositions[1])
 			{
 			{
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
+					GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[2])
 			if (0xFFFFFFFF != aiPositions[2])
 			{
 			{
 				vOut.z = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.z = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]);
+					GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]);
 			}
 			}
 
 
 			// and add them to our nice list
 			// and add them to our nice list
@@ -663,28 +682,28 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 			
 			
 			if (0xFFFFFFFF != aiPositions[0])
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 			{
-				vOut.r = NormalizeColorValue((*i).alProperties[
-					aiPositions[0]].avList.front(),aiTypes[0]);
+				vOut.r = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[0]).avList.front(),aiTypes[0]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[1])
 			if (0xFFFFFFFF != aiPositions[1])
 			{
 			{
-				vOut.g = NormalizeColorValue((*i).alProperties[
-					aiPositions[1]].avList.front(),aiTypes[1]);
+				vOut.g = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[1]).avList.front(),aiTypes[1]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[2])
 			if (0xFFFFFFFF != aiPositions[2])
 			{
 			{
-				vOut.b = NormalizeColorValue((*i).alProperties[
-					aiPositions[2]].avList.front(),aiTypes[2]);
+				vOut.b = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[2]).avList.front(),aiTypes[2]);
 			}
 			}
 
 
 			// assume 1.0 for the alpha channel ifit is not set
 			// assume 1.0 for the alpha channel ifit is not set
 			if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
 			if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
 			else
 			else
 			{
 			{
-				vOut.a = NormalizeColorValue((*i).alProperties[
-					aiPositions[3]].avList.front(),aiTypes[3]);
+				vOut.a = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[3]).avList.front(),aiTypes[3]);
 			}
 			}
 
 
 			// and add them to our nice list
 			// and add them to our nice list
@@ -777,11 +796,11 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				// parse the list of vertex indices
 				// parse the list of vertex indices
 				if (0xFFFFFFFF != iProperty)
 				if (0xFFFFFFFF != iProperty)
 				{
 				{
-					const unsigned int iNum = (unsigned int)(*i).alProperties[iProperty].avList.size();
+					const unsigned int iNum = (unsigned int)GetProperty((*i).alProperties, iProperty).avList.size();
 					sFace.mIndices.resize(iNum);
 					sFace.mIndices.resize(iNum);
 
 
 					std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = 
 					std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = 
-						(*i).alProperties[iProperty].avList.begin();
+						GetProperty((*i).alProperties, iProperty).avList.begin();
 
 
 					for (unsigned int a = 0; a < iNum;++a,++p)
 					for (unsigned int a = 0; a < iNum;++a,++p)
 					{
 					{
@@ -793,7 +812,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				if (0xFFFFFFFF != iMaterialIndex)
 				if (0xFFFFFFFF != iMaterialIndex)
 				{
 				{
 					sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
 					sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
-						(*i).alProperties[iMaterialIndex].avList.front(),eType2);
+						GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2);
 				}
 				}
 				pvOut->push_back(sFace);
 				pvOut->push_back(sFace);
 			}
 			}
@@ -804,7 +823,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 			// a value of -1 indicates a restart of the strip
 			// a value of -1 indicates a restart of the strip
 			bool flip = false;
 			bool flip = false;
 			for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
 			for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
-				const std::vector<PLY::PropertyInstance::ValueUnion>& quak = (*i).alProperties[iProperty].avList;
+				const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty((*i).alProperties, iProperty).avList;
 				pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
 				pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
 
 
 				int aiTable[2] = {-1,-1};
 				int aiTable[2] = {-1,-1};
@@ -855,30 +874,30 @@ void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avL
 	if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
 	if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
 	else
 	else
 	{
 	{
-		clrOut->r = NormalizeColorValue(avList[
-			aiPositions[0]].avList.front(),aiTypes[0]);
+		clrOut->r = NormalizeColorValue(GetProperty(avList,
+			aiPositions[0]).avList.front(),aiTypes[0]);
 	}
 	}
 
 
 	if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
 	if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
 	else
 	else
 	{
 	{
-		clrOut->g = NormalizeColorValue(avList[
-			aiPositions[1]].avList.front(),aiTypes[1]);
+		clrOut->g = NormalizeColorValue(GetProperty(avList,
+			aiPositions[1]).avList.front(),aiTypes[1]);
 	}
 	}
 
 
 	if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
 	if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
 	else
 	else
 	{
 	{
-		clrOut->b = NormalizeColorValue(avList[
-			aiPositions[2]].avList.front(),aiTypes[2]);
+		clrOut->b = NormalizeColorValue(GetProperty(avList,
+			aiPositions[2]).avList.front(),aiTypes[2]);
 	}
 	}
 
 
 	// assume 1.0 for the alpha channel ifit is not set
 	// assume 1.0 for the alpha channel ifit is not set
 	if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
 	if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
 	else
 	else
 	{
 	{
-		clrOut->a = NormalizeColorValue(avList[
-			aiPositions[3]].avList.front(),aiTypes[3]);
+		clrOut->a = NormalizeColorValue(GetProperty(avList, 
+			aiPositions[3]).avList.front(),aiTypes[3]);
 	}
 	}
 }
 }
 
 
@@ -1029,7 +1048,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
 			// handle phong power and shading mode
 			// handle phong power and shading mode
 			int iMode;
 			int iMode;
 			if (0xFFFFFFFF != iPhong)	{
 			if (0xFFFFFFFF != iPhong)	{
-				float fSpec = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),ePhong);
+				float fSpec = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),ePhong);
 
 
 				// if shininess is 0 (and the pow() calculation would therefore always
 				// if shininess is 0 (and the pow() calculation would therefore always
 				// become 1, not depending on the angle), use gouraud lighting
 				// become 1, not depending on the angle), use gouraud lighting
@@ -1047,7 +1066,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
 
 
 			// handle opacity
 			// handle opacity
 			if (0xFFFFFFFF != iOpacity)	{
 			if (0xFFFFFFFF != iOpacity)	{
-				float fOpacity = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),eOpacity);
+				float fOpacity = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),eOpacity);
 				pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
 				pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
 			}
 			}
 
 

+ 2 - 2
code/STLExporter.cpp

@@ -55,7 +55,7 @@ namespace Assimp	{
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp
-void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	STLExporter exporter(pFile, pScene);
 	STLExporter exporter(pFile, pScene);
@@ -68,7 +68,7 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
 
 
 	outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
 	outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
 }
 }
-void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	STLExporter exporter(pFile, pScene, true);
 	STLExporter exporter(pFile, pScene, true);

+ 3 - 1
code/SceneCombiner.cpp

@@ -1026,7 +1026,9 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate)
 	dest->mFlags = src->mFlags;
 	dest->mFlags = src->mFlags;
 
 
 	// source private data might be NULL if the scene is user-allocated (i.e. for use with the export API)
 	// source private data might be NULL if the scene is user-allocated (i.e. for use with the export API)
-	ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0;
+	if (dest->mPrivate != NULL) {
+		ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0;
+	}
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 3 - 0
code/Subdivision.cpp

@@ -289,6 +289,8 @@ void CatmullClarkSubdivider::InternSubdivide (
 		}
 		}
 	}
 	}
 	
 	
+	{
+	// we want edges to go away before the recursive calls so begin a new scope
 	EdgeMap edges;
 	EdgeMap edges;
 
 
 	// ---------------------------------------------------------------------
 	// ---------------------------------------------------------------------
@@ -571,6 +573,7 @@ void CatmullClarkSubdivider::InternSubdivide (
 			}
 			}
 		}
 		}
 	}
 	}
+	}  // end of scope for edges, freeing its memory
 
 
 	// ---------------------------------------------------------------------
 	// ---------------------------------------------------------------------
 	// 7. Apply the next subdivision step. 
 	// 7. Apply the next subdivision step. 

+ 28 - 9
code/XFileExporter.cpp

@@ -66,7 +66,7 @@ namespace Assimp
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
-void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	std::string path = "";
 	std::string path = "";
 	std::string file = pFile;
 	std::string file = pFile;
@@ -85,13 +85,19 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce
 		}
 		}
 	}
 	}
 
 
+	// create/copy Properties
+	ExportProperties props(*pProperties);
+
+	// set standard properties if not set
+	if (!props.HasPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT)) props.SetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT, false);
+
 	// invoke the exporter 
 	// invoke the exporter 
-	XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file);
+	XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props);
 
 
 	// we're still here - export successfully completed. Write result to the given IOSYstem
 	// we're still here - export successfully completed. Write result to the given IOSYstem
 	boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
 	boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
 	if(outfile == NULL) {
 	if(outfile == NULL) {
-		throw DeadlyExportError("could not open output .dae file: " + std::string(pFile));
+		throw DeadlyExportError("could not open output .x file: " + std::string(pFile));
 	}
 	}
 
 
 	// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
 	// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
@@ -103,7 +109,7 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor for a specific scene to export
 // Constructor for a specific scene to export
-XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
+XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties) : mIOSystem(pIOSystem), mPath(path), mFile(file), mProperties(pProperties)
 {
 {
 	// make sure that all formatting happens using the standard, C locale and not the user's current locale
 	// make sure that all formatting happens using the standard, C locale and not the user's current locale
 	mOutput.imbue( std::locale("C") );
 	mOutput.imbue( std::locale("C") );
@@ -133,7 +139,7 @@ void XFileExporter::WriteFile()
 {
 {
 	// note, that all realnumber values must be comma separated in x files
 	// note, that all realnumber values must be comma separated in x files
 	mOutput.setf(std::ios::fixed);
 	mOutput.setf(std::ios::fixed);
-	mOutput.precision(6); // precission for float
+	mOutput.precision(16); // precission for double
 
 
 	// entry of writing the file
 	// entry of writing the file
 	WriteHeader();
 	WriteHeader();
@@ -155,7 +161,10 @@ void XFileExporter::WriteFile()
 // Writes the asset header
 // Writes the asset header
 void XFileExporter::WriteHeader()
 void XFileExporter::WriteHeader()
 {
 {
-	mOutput << startstr << "xof 0303txt 0032" << endstr;
+	if (mProperties->GetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT) == true)
+		mOutput << startstr << "xof 0303txt 0064" << endstr;
+	else
+		mOutput << startstr << "xof 0303txt 0032" << endstr;
 	mOutput << endstr;
 	mOutput << endstr;
 	mOutput << startstr << "template Frame {" << endstr;
 	mOutput << startstr << "template Frame {" << endstr;
 	PushTag();
 	PushTag();
@@ -305,7 +314,7 @@ void XFileExporter::WriteNode( aiNode* pNode)
 		ss << "Node_" << pNode;
 		ss << "Node_" << pNode;
 		pNode->mName.Set(ss.str());
 		pNode->mName.Set(ss.str());
 	}
 	}
-	mOutput << startstr << "Frame " << pNode->mName.C_Str() << " {" << endstr;
+	mOutput << startstr << "Frame " << toXFileString(pNode->mName) << " {" << endstr;
 
 
 	PushTag();
 	PushTag();
 
 
@@ -325,9 +334,9 @@ void XFileExporter::WriteNode( aiNode* pNode)
 	mOutput << startstr << "}" << endstr << endstr;
 	mOutput << startstr << "}" << endstr << endstr;
 }
 }
 
 
-void XFileExporter::WriteMesh(const aiMesh* mesh)
+void XFileExporter::WriteMesh(aiMesh* mesh)
 {
 {
-	mOutput << startstr << "Mesh " << mesh->mName.C_Str() << "_mShape" << " {" << endstr;
+	mOutput << startstr << "Mesh " << toXFileString(mesh->mName) << "_mShape" << " {" << endstr;
 
 
 	PushTag();
 	PushTag();
 
 
@@ -503,6 +512,16 @@ void XFileExporter::WriteMesh(const aiMesh* mesh)
 
 
 }
 }
 
 
+std::string XFileExporter::toXFileString(aiString &name)
+{
+	std::string str = std::string(name.C_Str());
+	std::replace(str.begin(), str.end(), '<', '_');
+	std::replace(str.begin(), str.end(), '>', '_');
+	std::replace(str.begin(), str.end(), '{', '_');
+	std::replace(str.begin(), str.end(), '}', '_');
+	std::replace(str.begin(), str.end(), '$', '_');
+	return str;
+}
 
 
 void XFileExporter::writePath(aiString path)
 void XFileExporter::writePath(aiString path)
 {
 {

+ 8 - 2
code/XFileExporter.h

@@ -66,7 +66,7 @@ class XFileExporter
 {
 {
 public:
 public:
 	/// Constructor for a specific scene to export
 	/// Constructor for a specific scene to export
-	XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
+	XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties);
 
 
 	/// Destructor
 	/// Destructor
 	virtual ~XFileExporter();
 	virtual ~XFileExporter();
@@ -85,7 +85,7 @@ protected:
 	void WriteNode( aiNode* pNode );
 	void WriteNode( aiNode* pNode );
 
 
 	/// write a mesh entry of the scene
 	/// write a mesh entry of the scene
-	void WriteMesh(const aiMesh* mesh);
+	void WriteMesh( aiMesh* mesh);
 
 
 	/// Enters a new xml element, which increases the indentation
 	/// Enters a new xml element, which increases the indentation
 	void PushTag() { startstr.append( "  "); }
 	void PushTag() { startstr.append( "  "); }
@@ -99,6 +99,12 @@ public:
 
 
 protected:
 protected:
 
 
+	/// normalize the name to be accepted by xfile readers
+	std::string toXFileString(aiString &name);
+
+	/// hold the properties pointer
+	const ExportProperties* mProperties;
+
 	/// write a path
 	/// write a path
 	void writePath(aiString path);	
 	void writePath(aiString path);	
 
 

+ 7 - 1
code/XGLLoader.cpp

@@ -91,7 +91,7 @@ static const aiImporterDesc desc = {
 	"",
 	"",
 	"",
 	"",
 	"",
 	"",
-	aiImporterFlags_SupportTextFlavour,
+	aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
 	0,
 	0,
 	0,
 	0,
 	0,
 	0,
@@ -435,6 +435,12 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl
 		throw;
 		throw;
 	}
 	}
 
 
+	// FIX: since we used std::multimap<> to keep meshes by id, mesh order now depends on the behaviour
+	// of the multimap implementation with respect to the ordering of entries with same values.
+	// C++11 gives the guarantee that it uses insertion order, before it is implementation-specific.
+	// Sort by material id to always guarantee a deterministic result.
+	std::sort(meshes.begin(), meshes.end(), SortMeshByMaterialId(scope));
+
 	// link meshes to node
 	// link meshes to node
 	nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
 	nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
 	if (nd->mNumMeshes) {
 	if (nd->mNumMeshes) {

+ 11 - 0
code/XGLLoader.h

@@ -93,6 +93,7 @@ protected:
 
 
 private:
 private:
 
 
+	
 	struct TempScope
 	struct TempScope
 	{
 	{
 		TempScope()
 		TempScope()
@@ -129,6 +130,16 @@ private:
 		aiLight* light;
 		aiLight* light;
 	};
 	};
 
 
+
+	struct SortMeshByMaterialId {
+		SortMeshByMaterialId(const TempScope& scope) : scope(scope) {}
+		bool operator()(unsigned int a, unsigned int b) const {
+			return scope.meshes_linear[a]->mMaterialIndex < scope.meshes_linear[b]->mMaterialIndex;
+		};
+
+		const TempScope& scope;
+	};
+
 	struct TempMesh
 	struct TempMesh
 	{
 	{
 		std::map<unsigned int, aiVector3D> points;
 		std::map<unsigned int, aiVector3D> points;

+ 17 - 0
code/fast_atof.h

@@ -223,6 +223,23 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
 	return value;
 	return value;
 }
 }
 
 
+// ------------------------------------------------------------------------------------
+// signed variant of strtoul10_64
+// ------------------------------------------------------------------------------------
+inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0)
+{
+	bool inv = (*in == '-');
+	if (inv || *in == '+')
+		++in;
+
+	int64_t value = strtoul10_64(in, out, max_inout);
+	if (inv) {
+		value = -value;
+	}
+	return value;
+}
+
+
 // Number of relevant decimals for floating-point parsing.
 // Number of relevant decimals for floating-point parsing.
 #define AI_FAST_ATOF_RELAVANT_DECIMALS 15
 #define AI_FAST_ATOF_RELAVANT_DECIMALS 15
 
 

+ 64 - 0
contrib/openddlparser/CMakeLists.txt

@@ -0,0 +1,64 @@
+CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
+PROJECT( OpenDDL-Parser )
+SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
+SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
+SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
+SET ( OPENDDL_PARSER_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} )
+SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
+
+if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+    find_package(Threads)
+else()
+    add_definitions( -D_CRT_SECURE_NO_WARNINGS )
+endif()
+
+add_definitions( -DOPENDDLPARSER_BUILD )
+add_definitions( -DOPENDDL_NO_USE_CPP11 )
+add_definitions( -D_VARIADIC_MAX=10 )
+
+INCLUDE_DIRECTORIES(
+    ./
+    include/
+    contrib/gtest-1.7.0/include
+    contrib/gtest-1.7.0/
+)
+
+link_directories(
+    ./
+)
+
+SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
+
+if( WIN32 AND NOT CYGWIN )
+  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" )  # Force to always compile with W4
+  if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
+    string( REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
+  else()
+    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4" )
+  endif()
+elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+  # Update if necessary
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++0x")
+elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
+endif()
+
+SET ( openddl_parser_src
+    code/OpenDDLParser.cpp
+    code/DDLNode.cpp
+    code/Value.cpp
+    include/openddlparser/OpenDDLParser.h
+    include/openddlparser/OpenDDLParserUtils.h
+    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/DDLNode.h
+    include/openddlparser/Value.h
+    README.md
+)
+ 
+SOURCE_GROUP( code            FILES ${openddl_parser_src} )
+
+ADD_LIBRARY( openddl_parser SHARED
+    ${openddl_parser_src}
+)

+ 111 - 0
contrib/openddlparser/README.md

@@ -0,0 +1,111 @@
+The OpenDDL-Parser
+==================
+
+A simple and fast OpenDDL Parser
+Current build status: [![Build Status](https://travis-ci.org/kimkulling/openddl-parser.png)](https://travis-ci.org/kimkulling/openddl-parser)
+
+Get the source code
+===================
+You can get the code from our git repository, which is located at GitHub. You can clone the repository like:
+
+> git clone https://github.com/kimkulling/openddl-parser.git
+
+Build from repo
+===============
+To build the library you need to install cmake first ( see http://www.cmake.org/ for more information ). Make also sure that a compiler toolchain is installed on your machine.
+After installing it you can open a console and type:
+
+> cmake CMakeLists.txt
+
+This command will generate a build environment for your installed build enrironment ( for Visual Studio the project files will be generated, for gcc the makefiles will be generated ).
+When using an IDE open the IDE and run the build. When using GNU-make type in your console:
+
+> make
+
+and that's all.
+
+Use the library
+===============
+To use the OpenDDL-parser you need to build the lib first. Now add the 
+> <Repo-folder>/include 
+
+to your include-path and the 
+
+> <Repo-folder>/lib
+
+to your lib-folder. Link the openddl.lib to your application. 
+
+Here is a small example how to use the lib:
+
+```cpp
+
+#include <iostream>
+#include <cassert>
+#include <openddlparser/OpenDDLParser.h>
+
+USE_ODDLPARSER_NS;
+
+int main( int argc, char *argv[] ) {
+    if( argc < 3 ) {
+        return 1;
+    }
+
+    char *filename( nullptr );
+    if( 0 == strncmp( FileOption, argv[ 1 ], strlen( FileOption ) ) ) {
+        filename = argv[ 2 ];
+    }
+    std::cout << "file to import: " << filename << std::endl;   
+    if( nullptr == filename ) {
+        std::cerr << "Invalid filename." << std::endl;
+        return Error;
+    }
+
+    FILE *fileStream = fopen( filename, "r+" );
+    if( NULL == filename ) {
+        std::cerr << "Cannot open file " << filename << std::endl;
+        return 1;
+    }
+
+    // obtain file size:
+    fseek( fileStream, 0, SEEK_END );
+    const size_t size( ftell( fileStream ) );   
+    rewind( fileStream );   
+    if( size > 0 ) {
+        char *buffer = new char[ size ];
+        const size_t readSize( fread( buffer, sizeof( char ), size, fileStream ) );
+        assert( readSize == size );
+        OpenDDLParser theParser;
+        theParser.setBuffer( buffer, size );
+        const bool result( theParser.parse() );
+        if( !result ) {
+            std::cerr << "Error while parsing file " << filename << "." << std::endl;
+        }
+    }
+    return 0;
+}
+
+```
+
+How to access the imported data
+===============================
+The data is organized as a tree. You can get the root tree with the following code:
+
+```
+OpenDDLParser theParser;
+theParser.setBuffer( buffer, size );
+const bool result( theParser.parse() );
+if ( result ) {
+    DDLNode *root = theParser.getRoot();
+
+    DDLNode::DllNodeList childs = root->getChildNodeList();
+    for ( size_t i=0; i<childs.size(); i++ ) {
+        DDLNode *child = childs[ i ];
+        Property *prop = child->getProperty(); // to get properties
+        std:.string type = child->getType();   // to get the node type
+        Value *values = child->getValue();     // to get the data;
+    }
+}
+
+```
+
+The instance called root contains the data.

+ 184 - 0
contrib/openddlparser/code/DDLNode.cpp

@@ -0,0 +1,184 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParser.h>
+
+#include <algorithm>
+
+BEGIN_ODDLPARSER_NS
+
+DDLNode::DllNodeList DDLNode::s_allocatedNodes;
+
+template<class T>
+inline
+static void releaseDataType( T *ptr ) {
+    if( ddl_nullptr == ptr ) {
+        return;
+    }
+
+    T *current( ddl_nullptr );
+    while( ptr ) {
+        current = ptr;
+        ptr = ptr->m_next;
+        delete current;
+    }
+}
+
+static void releaseReferencedNames( Reference *ref ) {
+    if( ddl_nullptr == ref ) {
+        return;
+    }
+
+    if( ref->m_referencedName ) {
+        for( size_t i = 0; i < ref->m_numRefs; i++ ) {
+            delete ref->m_referencedName;
+        }
+    }
+}
+
+DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent )
+: m_type( type )
+, m_name( name )
+, m_parent( parent )
+, m_children()
+, m_properties( ddl_nullptr )
+, m_value( ddl_nullptr )
+, m_dtArrayList( ddl_nullptr )
+, m_references( ddl_nullptr )
+, m_idx( idx ) {
+    if( m_parent ) {
+        m_parent->m_children.push_back( this );
+    }
+}
+
+DDLNode::~DDLNode() {
+    releaseDataType<Property>( m_properties );
+    releaseDataType<Value>( m_value );
+    releaseReferencedNames( m_references );
+
+    delete m_dtArrayList;
+    m_dtArrayList = ddl_nullptr;
+    if( s_allocatedNodes[ m_idx ] == this ) {
+        s_allocatedNodes[ m_idx ] = ddl_nullptr;
+    }
+}
+
+void DDLNode::attachParent( DDLNode *parent ) {
+    if( m_parent == parent ) {
+        return;
+    }
+
+    m_parent = parent;
+    if( ddl_nullptr != m_parent ) {
+        m_parent->m_children.push_back( this );
+    }
+}
+
+void DDLNode::detachParent() {
+    if( m_parent ) {
+        std::vector<DDLNode*>::iterator it;
+        it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this );
+        if( m_parent->m_children.end() != it ) {
+            m_parent->m_children.erase( it );
+        }
+        m_parent = ddl_nullptr;
+    }
+}
+
+DDLNode *DDLNode::getParent() const {
+    return m_parent;
+}
+
+const DDLNode::DllNodeList &DDLNode::getChildNodeList() const {
+    return m_children;
+}
+
+void DDLNode::setType( const std::string &type ) {
+    m_type = type;
+}
+
+const std::string &DDLNode::getType() const {
+    return m_type;
+}
+
+
+void DDLNode::setName( const std::string &name ) {
+    m_name = name;
+}
+
+const std::string &DDLNode::getName() const {
+    return m_name;
+}
+
+void DDLNode::setProperties( Property *prop ) {
+    m_properties = prop;
+}
+
+Property *DDLNode::getProperties() const {
+    return m_properties;
+}
+
+void DDLNode::setValue( Value *val ) {
+    m_value = val;
+}
+
+Value *DDLNode::getValue() const {
+    return m_value;
+}
+
+void DDLNode::setDataArrayList( DataArrayList  *dtArrayList ) {
+    m_dtArrayList = dtArrayList;
+}
+
+DataArrayList *DDLNode::getDataArrayList() const {
+    return m_dtArrayList;
+}
+
+void DDLNode::setReferences( Reference *refs ) {
+    m_references = refs;
+}
+
+Reference *DDLNode::getReferences() const {
+    return m_references;
+}
+
+DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
+    const size_t idx( s_allocatedNodes.size() );
+    DDLNode *node = new DDLNode( type, name, idx, parent );
+    s_allocatedNodes.push_back( node );
+    
+    return node;
+}
+
+void DDLNode::releaseNodes() {
+    if( s_allocatedNodes.size() > 0 ) {
+        for( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
+            if( *it ) {
+                delete *it;
+            }
+        }
+        s_allocatedNodes.clear();
+    }
+}
+
+END_ODDLPARSER_NS

+ 911 - 0
contrib/openddlparser/code/OpenDDLParser.cpp

@@ -0,0 +1,911 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLParser.h>
+
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <math.h>
+
+#ifdef _WIN32
+#  include <windows.h>
+#endif // _WIN32
+
+#define DEBUG_HEADER_NAME 
+
+BEGIN_ODDLPARSER_NS
+
+static const char *Version = "0.1.0";
+
+namespace Grammar {
+    static const char *OpenBracketToken   = "{";
+    static const char *CloseBracketToken  = "}";
+    static const char *OpenPropertyToken  = "(";
+    static const char *ClosePropertyToken = ")";
+    static const char *BoolTrue           = "true";
+    static const char *BoolFalse          = "false";
+    static const char *RefToken           = "ref";
+    static const char *CommaSeparator     = ",";
+
+    static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
+        "bool",
+        "int8",
+        "int16",
+        "int32",
+        "int64",
+        "unsigned_int8",
+        "unsigned_int16",
+        "unsigned_int32",
+        "unsigned_int64",
+        "half",
+        "float",
+        "double",
+        "string",
+        "ref"
+    };
+} // Namespace Grammar
+
+
+static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
+    std::stringstream stream;
+    stream << "Invalid token " << *in << ", " << exp << " expected." << std::endl;
+    callback( ddl_error_msg, stream.str() );
+}
+
+static bool isIntegerType( Value::ValueType integerType ) {
+    if( integerType != Value::ddl_int8 && integerType != Value::ddl_int16 && 
+            integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
+        return false;
+    }
+
+    return true;
+}
+
+static DDLNode *createDDLNode( Identifier *id, OpenDDLParser *parser ) {
+    if( ddl_nullptr == id || ddl_nullptr == parser ) {
+        return ddl_nullptr;
+    }
+
+    const std::string type( id->m_buffer );
+    DDLNode *parent( parser->top() );
+    DDLNode *node = DDLNode::create( type, "", parent );
+
+    return node;
+}
+
+static void logMessage( LogSeverity severity, const std::string &msg ) {
+    std::string log;
+    if( ddl_debug_msg == severity ) {
+        log += "Debug:";
+    } else if( ddl_info_msg == severity ) {
+        log += "Info :";
+    } else if( ddl_warn_msg == severity ) {
+        log += "Warn :";
+    } else if( ddl_error_msg == severity ) {
+        log += "Error:";
+    } else {
+        log += "None :";
+    }
+
+    log += msg;
+    std::cout << log;
+}
+
+OpenDDLParser::OpenDDLParser()
+: m_logCallback( logMessage )
+, m_buffer()
+, m_stack()
+, m_context( ddl_nullptr ) {
+    // empty
+}
+
+OpenDDLParser::OpenDDLParser( char *buffer, size_t len )
+: m_logCallback( &logMessage )
+, m_buffer()
+, m_context( ddl_nullptr ) {
+    if( 0 != len ) {
+        setBuffer( buffer, len );
+    }
+}
+
+OpenDDLParser::~OpenDDLParser() {
+    clear();
+}
+
+void OpenDDLParser::setLogCallback( logCallback callback ) {
+    if( ddl_nullptr != callback ) {
+        // install user-specific log callback
+        m_logCallback = callback;
+    } else {
+        // install default log callback
+        m_logCallback = &logMessage;
+    }
+}
+
+OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const {
+    return m_logCallback;
+}
+
+void OpenDDLParser::setBuffer( char *buffer, size_t len ) {
+    clear();
+    if( 0 == len ) {
+        return;
+    }
+
+    m_buffer.resize( len );
+    ::memcpy(&m_buffer[ 0 ], buffer, len );
+}
+
+void OpenDDLParser::setBuffer( const std::vector<char> &buffer ) {
+    clear();
+    m_buffer.resize( buffer.size() );
+    std::copy( buffer.begin(), buffer.end(), m_buffer.begin() );
+}
+
+const char *OpenDDLParser::getBuffer() const {
+    if( m_buffer.empty() ) {
+        return ddl_nullptr;
+    }
+
+    return &m_buffer[ 0 ];
+}
+
+size_t OpenDDLParser::getBufferSize() const {
+    return m_buffer.size();
+}
+
+void OpenDDLParser::clear() {
+    m_buffer.resize( 0 );
+    if( m_context ) {
+        m_context->m_root = ddl_nullptr;
+    }
+
+    DDLNode::releaseNodes();
+}
+
+bool OpenDDLParser::parse() {
+    if( m_buffer.empty() ) {
+        return false;
+    }
+    
+    normalizeBuffer( m_buffer );
+
+    std::cout << &m_buffer[0] << std::endl;
+
+    m_context = new Context;
+    m_context->m_root = DDLNode::create( "root", "", ddl_nullptr );
+    pushNode( m_context->m_root );
+
+    // do the main parsing
+    char *current( &m_buffer[ 0 ] );
+    char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 );
+    size_t pos( current - &m_buffer[ 0 ] );
+    while( pos < m_buffer.size() ) {
+        current = parseNextNode( current, end );
+        pos = current - &m_buffer[ 0 ];
+    }
+    return true;
+}
+
+char *OpenDDLParser::parseNextNode( char *in, char *end ) {
+    in = parseHeader( in, end );
+    in = parseStructure( in, end );
+
+    return in;
+}
+
+static void dumpId( Identifier *id ) {
+    if( ddl_nullptr != id ) {
+        std::cout << id->m_buffer << std::endl;
+    }
+}
+
+char *OpenDDLParser::parseHeader( char *in, char *end ) {
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    Identifier *id( ddl_nullptr );
+    in = OpenDDLParser::parseIdentifier( in, end, &id );
+
+#ifdef DEBUG_HEADER_NAME    
+    dumpId( id );
+#endif // DEBUG_HEADER_NAME
+
+    in = lookForNextToken( in, end );
+    Property *first( ddl_nullptr );
+    if( ddl_nullptr != id ) {
+        if( *in == '(' ) {
+            in++;
+            Property *prop( ddl_nullptr ), *prev( ddl_nullptr );
+            while( *in != ')' && in != end ) {
+                in = OpenDDLParser::parseProperty( in, end, &prop );
+                in = lookForNextToken( in, end );
+
+                if( *in != ',' && *in != ')' ) {
+                    logInvalidTokenError( in, ")", m_logCallback );
+                    return in;
+                }
+                
+                if( ddl_nullptr != prop && *in != ',' ) {
+                    if( ddl_nullptr == first ) {
+                        first = prop;
+                    }
+                    if( ddl_nullptr != prev ) {
+                        prev->m_next = prop;
+                    }
+                    prev = prop;
+                }
+            }
+            in++;
+        }
+
+        // store the node
+        DDLNode *node( createDDLNode( id, this ) );
+        if( ddl_nullptr != node ) {
+            pushNode( node );
+        } else {
+            std::cerr << "nullptr returned by creating DDLNode." << std::endl;
+        }
+
+        // set the properties
+        if( ddl_nullptr != first ) {
+            node->setProperties( first );
+        }
+
+        Name *name( ddl_nullptr );
+        in = OpenDDLParser::parseName( in, end, &name );
+        if( ddl_nullptr != name ) {
+            const std::string nodeName( name->m_id->m_buffer );
+            node->setName( nodeName );
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseStructure( char *in, char *end ) {
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    bool error( false );
+    in = lookForNextToken( in, end );
+    if( *in == '{' ) {
+        // loop over all children ( data and nodes )
+        do {
+            in = parseStructureBody( in, end, error );
+        } while ( *in != '}' );
+        in++;
+    } else {
+        in++;
+        logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
+        error = true;
+        return in;
+    }
+    in = lookForNextToken( in, end );
+    
+    // pop node from stack after successful parsing
+    if( !error ) {
+        popNode();
+    }
+
+    return in;
+}
+
+static void setNodeValues( DDLNode *currentNode, Value *values ) {
+    if( ddl_nullptr != values ){
+        if( ddl_nullptr != currentNode ) {
+            currentNode->setValue( values );
+        }
+    }
+}
+
+static void setNodeReferences( DDLNode *currentNode, Reference *refs ) {
+    if( ddl_nullptr != refs ) {
+        if( ddl_nullptr != currentNode ) {
+            currentNode->setReferences( refs );
+        }
+    }
+}
+
+static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayList ) {
+    if( ddl_nullptr != dtArrayList ) {
+        if( ddl_nullptr != currentNode ) {
+            currentNode->setDataArrayList( dtArrayList );
+        }
+    }
+}
+
+char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
+    if( !isNumeric( *in ) && !isCharacter( *in ) ) {
+        in++;
+    }
+
+    in = lookForNextToken( in, end );
+    Value::ValueType type( Value::ddl_none );
+    size_t arrayLen( 0 );
+    in = OpenDDLParser::parsePrimitiveDataType( in, end, type, arrayLen );
+    if( Value::ddl_none != type ) {
+        // parse a primitive data type
+        in = lookForNextToken( in, end );
+        if( *in == '{' ) {
+            Reference *refs( ddl_nullptr );
+            DataArrayList *dtArrayList( ddl_nullptr );
+            Value *values( ddl_nullptr );
+            if( 1 == arrayLen ) {
+                size_t numRefs( 0 ), numValues( 0 );
+                in = parseDataList( in, end, &values, numValues, &refs, numRefs );
+                setNodeValues( top(), values );
+                setNodeReferences( top(), refs );
+            } else if( arrayLen > 1 ) {
+                in = parseDataArrayList( in, end, &dtArrayList );
+                setNodeDataArrayList( top(), dtArrayList );
+            } else {
+                std::cerr << "0 for array is invalid." << std::endl;
+                error = true;
+            }
+        }
+
+        in = lookForNextToken( in, end );
+        if( *in != '}' ) {
+            logInvalidTokenError( in, std::string( Grammar::CloseBracketToken ), m_logCallback );
+        } else {
+            //in++;
+        }
+    } else {
+        // parse a complex data type
+        in = parseNextNode( in, end );
+    }
+
+    return in;
+}
+
+void OpenDDLParser::pushNode( DDLNode *node ) {
+    if( ddl_nullptr == node ) {
+        return;
+    }
+
+    m_stack.push_back( node );
+}
+
+DDLNode *OpenDDLParser::popNode() {
+    if( m_stack.empty() ) {
+        return ddl_nullptr;
+    }
+
+    DDLNode *topNode( top() );
+    m_stack.pop_back();
+
+    return topNode;
+}
+
+DDLNode *OpenDDLParser::top() {
+    if( m_stack.empty() ) {
+        return ddl_nullptr;
+    }
+    
+    DDLNode *top( m_stack.back() );
+    return top;
+}
+
+DDLNode *OpenDDLParser::getRoot() const {
+    if( ddl_nullptr == m_context ) {
+        return ddl_nullptr;
+    }
+
+    return m_context->m_root;
+}
+
+Context *OpenDDLParser::getContext() const {
+    return m_context;
+}
+
+void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) {
+    if( buffer.empty() ) {
+        return;
+    }
+
+    std::vector<char> newBuffer;
+    const size_t len( buffer.size() );
+    char *end( &buffer[ len-1 ] + 1 );
+    for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
+        char *c( &buffer[readIdx] );
+        // check for a comment
+        if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
+            newBuffer.push_back( buffer[ readIdx ] );
+        } else {
+            if( isComment<char>( c, end ) ) {
+                readIdx++;
+                // skip the comment and the rest of the line
+                while( !isEndofLine( buffer[ readIdx ] ) ) {
+                    readIdx++;
+                }
+            }
+        }
+    }
+    buffer = newBuffer;
+}
+
+char *OpenDDLParser::parseName( char *in, char *end, Name **name ) {
+    *name = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    // ignore blanks
+    in = lookForNextToken( in, end );
+    if( *in != '$' && *in != '%' ) {
+        return in;
+    }
+
+    NameType ntype( GlobalName );
+    if( *in == '%' ) {
+        ntype = LocalName;
+    }
+
+    Name *currentName( ddl_nullptr );
+    Identifier *id( ddl_nullptr );
+    in = parseIdentifier( in, end, &id );
+    if( id ) {
+        currentName = new Name( ntype, id );
+        if( currentName ) {
+            *name = currentName;
+        }
+    }
+    
+    return in;
+}
+
+char *OpenDDLParser::parseIdentifier( char *in, char *end, Identifier **id ) {
+    *id = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    // ignore blanks
+    in = lookForNextToken( in, end );
+    
+    // staring with a number is forbidden
+    if( isNumeric<const char>( *in ) ) {
+        return in;
+    }
+
+    // get size of id
+    size_t idLen( 0 );
+    char *start( in );
+    while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != '(' && *in != ')' ) {
+        in++;
+        idLen++;
+    }
+    
+    const size_t len( idLen + 1 );
+    Identifier *newId = new Identifier( len, new char[ len ] );
+    ::strncpy( newId->m_buffer, start, newId->m_len-1 );
+    newId->m_buffer[ newId->m_len - 1 ] = '\0';
+    *id = newId;
+
+    return in;
+}
+
+char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len ) {
+    type = Value::ddl_none;
+    len = 0;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    size_t prim_len( 0 );
+    for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
+        prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] );
+        if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) {
+            type = ( Value::ValueType ) i;
+            break;
+        }
+    }
+
+    if( Value::ddl_none == type ) {
+        in = lookForNextToken( in, end );
+        return in;
+    } else {
+        in += prim_len;
+    }
+
+    bool ok( true );
+    if( *in == '[' ) {
+        ok = false;
+        in++;
+        char *start( in );
+        while ( in != end ) {
+            in++;
+            if( *in == ']' ) {
+                len = atoi( start );
+                ok = true;
+                in++;
+                break;
+            }
+        }
+    } else {
+        len = 1;
+    }
+    if( !ok ) {
+        type = Value::ddl_none;
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseReference( char *in, char *end, std::vector<Name*> &names ) {
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    Name *nextName( ddl_nullptr );
+    in = parseName( in, end, &nextName );
+    if( nextName ) {
+        names.push_back( nextName );
+    }
+    while( ',' == *in ) {
+        in = getNextSeparator( in, end );
+        if( ',' == *in ) {
+            in = parseName( in, end, &nextName );
+            if( nextName ) {
+                names.push_back( nextName );
+            }
+        } else {
+            break;
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean ) {
+    *boolean = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    char *start( in );
+    size_t len( 0 );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+        len++;
+    }
+    len++;
+    int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
+    if( 0 != res ) {
+        res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
+        if( 0 != res ) {
+            *boolean = ddl_nullptr;
+            return in;
+        }
+        *boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
+        (*boolean)->setBool( false );
+    } else {
+        *boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
+        (*boolean)->setBool( true );
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer, Value::ValueType integerType ) {
+    *integer = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    if( !isIntegerType( integerType ) ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    char *start( in );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+    }
+
+    if( isNumeric( *start ) ) {
+        const int value( atoi( start ) );
+        *integer = ValueAllocator::allocPrimData( integerType );
+        switch( integerType ) {
+            case Value::ddl_int8:
+                    ( *integer )->setInt8( (int8) value );
+                    break;
+            case Value::ddl_int16:
+                    ( *integer )->setInt16( ( int16 ) value );
+                    break;
+            case Value::ddl_int32:
+                    ( *integer )->setInt32( ( int32 ) value );
+                    break;
+            case Value::ddl_int64:
+                    ( *integer )->setInt64( ( int64 ) value );
+                    break;
+            default:
+                break;
+        }
+    } 
+
+    return in;
+}
+
+char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating ) {
+    *floating = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    char *start( in );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+    }
+
+    // parse the float value
+    bool ok( false );
+    if( isNumeric( *start ) ) {
+        ok = true;
+    } else {
+        if( *start == '-' ) {
+            if( isNumeric( *(start+1) ) ) {
+                ok = true;
+            }
+        }
+    }
+
+    if( ok ) {
+        const float value( ( float ) atof( start ) );
+        *floating = ValueAllocator::allocPrimData( Value::ddl_float );
+        ( *floating )->setFloat( value );
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseStringLiteral( char *in, char *end, Value **stringData ) {
+    *stringData = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    size_t len( 0 );
+    char *start( in );
+    if( *start == '\"' ) {
+        start++;
+        in++;
+        while( *in != '\"' && in != end ) {
+            in++;
+            len++;
+        }
+
+        *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
+        ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
+        ( *stringData )->m_data[len] = '\0';
+        in++;
+    }
+
+    return in;
+}
+
+static void createPropertyWithData( Identifier *id, Value *primData, Property **prop ) {
+    if( ddl_nullptr != primData ) {
+        ( *prop ) = new Property( id );
+        ( *prop )->m_primData = primData;
+    }
+}
+
+char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
+    *data = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    if( *in != '0' ) {
+        return in;
+    }
+
+    in++;
+    if( *in != 'x' && *in != 'X' ) {
+        return in;
+    }
+
+    in++;
+    bool ok( true );
+    char *start( in );
+    int pos( 0 );
+    while( !isSeparator( *in ) && in != end ) {
+        if( ( *in < '0' && *in > '9' ) || ( *in < 'a' && *in > 'f' ) || ( *in < 'A' && *in > 'F' ) ) {
+            ok = false;
+            break;
+        }
+        pos++;
+        in++;
+    }
+
+    if( !ok ) {
+        return in;
+    }
+
+    int value( 0 );
+    while( pos > 0 ) {
+        int v = hex2Decimal( *start );
+        pos--;
+        value = ( value << 4 ) | v;
+        start++;
+    }
+
+    *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 );
+    if( ddl_nullptr != *data ) {
+        ( *data )->setUnsignedInt64( value );
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
+    *prop = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    Identifier *id( ddl_nullptr );
+    in = parseIdentifier( in, end, &id );
+    if( ddl_nullptr != id ) {
+        in = lookForNextToken( in, end );
+        if( *in == '=' ) {
+            in++;
+            in = getNextToken( in, end );
+            Value *primData( ddl_nullptr );
+            if( isInteger( in, end ) ) {
+                in = parseIntegerLiteral( in, end, &primData );
+                createPropertyWithData( id, primData, prop );
+            } else if( isFloat( in, end ) ) {
+                in = parseFloatingLiteral( in, end, &primData );
+                createPropertyWithData( id, primData, prop );
+            } else if( isStringLiteral( *in ) ) { // string data
+                in = parseStringLiteral( in, end, &primData );
+                createPropertyWithData( id, primData, prop );
+            } else {                          // reference data
+                std::vector<Name*> names;
+                in = parseReference( in, end, names );
+                if( !names.empty() ) {
+                    Reference *ref = new Reference( names.size(), &names[ 0 ] );
+                    ( *prop ) = new Property( id );
+                    ( *prop )->m_ref = ref;
+                }
+            }
+        } 
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseDataList( char *in, char *end, Value **data, size_t &numValues, Reference **refs, size_t &numRefs ) {
+    *data = ddl_nullptr;
+    numValues = numRefs = 0;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    if( *in == '{' ) {
+        in++;
+        Value *current( ddl_nullptr ), *prev( ddl_nullptr );
+        while( '}' != *in ) {
+            current = ddl_nullptr;
+            in = lookForNextToken( in, end );
+            if( isInteger( in, end ) ) {
+                in = parseIntegerLiteral( in, end, &current );
+            } else if( isFloat( in, end ) ) {
+                in = parseFloatingLiteral( in, end, &current );
+            } else if( isStringLiteral( *in ) ) {
+                in = parseStringLiteral( in, end, &current );
+            } else if( isHexLiteral( in, end ) ) {
+                in = parseHexaLiteral( in, end, &current );
+            } else {                          // reference data
+                std::vector<Name*> names;
+                in = parseReference( in, end, names );
+                if( !names.empty() ) {
+                    Reference *ref = new Reference( names.size(), &names[ 0 ] );
+                    *refs = ref;
+                    numRefs = names.size();
+                }
+            }
+
+            if( ddl_nullptr != current ) {
+                if( ddl_nullptr == *data ) {
+                    *data = current;
+                    prev = current;
+                } else {
+                    prev->setNext( current );
+                    prev = current;
+                }
+                numValues++;
+            }
+
+            in = getNextSeparator( in, end );
+            if( ',' != *in && '}' != *in && !isSpace( *in ) ) {
+                break;
+            }
+        }
+        in++;
+    }
+
+    return in;
+}
+
+static DataArrayList *createDataArrayList( Value *currentValue, size_t numValues ) {
+    DataArrayList *dataList = new DataArrayList;
+    dataList->m_dataList = currentValue;
+    dataList->m_numItems = numValues;
+
+    return dataList;
+
+}
+char *OpenDDLParser::parseDataArrayList( char *in, char *end, DataArrayList **dataList ) {
+    *dataList = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    if( *in == Grammar::OpenBracketToken[ 0 ] ) {
+        in++;
+        Value *currentValue( ddl_nullptr );
+        Reference *refs( ddl_nullptr );
+        DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
+        do {
+            size_t numRefs( 0 ), numValues( 0 );
+            currentValue = ddl_nullptr;
+            in = parseDataList( in, end, &currentValue, numValues, &refs, numRefs );
+            if( ddl_nullptr != currentValue ) {
+                if( ddl_nullptr == prev ) {
+                    *dataList = createDataArrayList( currentValue, numValues );
+                    prev = *dataList;
+                } else {
+                    currentDataList = createDataArrayList( currentValue, numValues );
+                    if( ddl_nullptr != prev ) {
+                        prev->m_next = currentDataList;
+                        prev = currentDataList;
+                    }
+                }
+            }
+        } while( Grammar::CommaSeparator[ 0 ] == *in && in != end );
+        in = lookForNextToken( in, end );
+        in++;
+    }
+
+    return in;
+}
+
+const char *OpenDDLParser::getVersion() {
+    return Version;
+}
+
+END_ODDLPARSER_NS

+ 297 - 0
contrib/openddlparser/code/Value.cpp

@@ -0,0 +1,297 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/Value.h>
+
+#include <iostream>
+#include <cassert>
+
+BEGIN_ODDLPARSER_NS
+
+Value::Value()
+: m_type( ddl_none )
+, m_size( 0 )
+, m_data( ddl_nullptr )
+, m_next( ddl_nullptr ) {
+    // empty
+}
+
+Value::~Value() {
+    // empty
+}
+
+void Value::setBool( bool value ) {
+    assert( ddl_bool == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+bool Value::getBool() {
+    assert( ddl_bool == m_type );
+    return ( bool ) ( *m_data );
+}
+
+void Value::setInt8( int8 value ) {
+    assert( ddl_int8 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int8 Value::getInt8() {
+    assert( ddl_int8 == m_type );
+    return ( int8 ) ( *m_data );
+}
+
+void Value::setInt16( int16 value ) {
+    assert( ddl_int16 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int16 Value::getInt16() {
+    assert( ddl_int16 == m_type );
+    return ( int16 ) ( *m_data );
+}
+
+void Value::setInt32( int32 value ) {
+    assert( ddl_int32 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int32 Value::getInt32() {
+    assert( ddl_int32 == m_type );
+    return ( int32 ) ( *m_data );
+}
+
+void Value::setInt64( int64 value ) {
+    assert( ddl_int32 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int64 Value::getInt64() {
+    return ( int64 ) ( *m_data );
+}
+
+void Value::setUnsignedInt8( uint8 value ) {
+    assert( ddl_unsigned_int8 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+uint8 Value::getUnsignedInt8() const {
+    assert( ddl_unsigned_int8 == m_type );
+    return ( uint8 ) ( *m_data );
+}
+
+void Value::setUnsignedInt16( uint16 value ) {
+    assert( ddl_unsigned_int16 == m_type );
+    ::memcpy( m_data, &value, m_size );
+
+}
+uint16 Value::getUnsignedInt16() const {
+    assert( ddl_unsigned_int16 == m_type );
+    return ( uint8 ) ( *m_data );
+
+}
+
+void Value::setUnsignedInt32( uint32 value ) {
+    assert( ddl_unsigned_int32 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+uint32 Value::getUnsignedInt32() const {
+    assert( ddl_unsigned_int32 == m_type );
+    return ( uint8 ) ( *m_data );
+}
+
+void Value::setUnsignedInt64( uint64 value ) {
+    assert( ddl_unsigned_int64 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+uint64 Value::getUnsignedInt64() const {
+    assert( ddl_unsigned_int64 == m_type );
+    return ( uint64 ) ( *m_data );
+}
+
+void Value::setFloat( float value ) {
+    assert( ddl_float == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+float Value::getFloat() const {
+    float v;
+    ::memcpy( &v, m_data, m_size );
+    return v;
+}
+
+void Value::setDouble( double value ) {
+    assert( ddl_double == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+double Value::getDouble() const {
+    double v;
+    ::memcpy( &v, m_data, m_size );
+    return v;
+}
+
+void Value::setString( const std::string &str ) {
+    assert( ddl_string == m_type );
+    ::memcpy( m_data, str.c_str(), str.size() );
+    m_data[ str.size() ] = '\0';
+}
+const char *Value::getString() const {
+    return (const char*) m_data;
+}
+
+void Value::dump() {
+    switch( m_type ) {
+    case ddl_none:
+        std::cout << "None" << std::endl;
+        break;
+    case ddl_bool:
+        std::cout << getBool() << std::endl;
+        break;
+    case ddl_int8:
+        std::cout << getInt8() << std::endl;
+        break;
+    case ddl_int16:
+        std::cout << getInt16() << std::endl;
+        break;
+    case ddl_int32:
+        std::cout << getInt32() << std::endl;
+        break;
+    case ddl_int64:
+        std::cout << getInt64() << std::endl;
+        break;
+    case ddl_unsigned_int8:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int16:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int32:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int64:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_half:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_float:
+        std::cout << getFloat() << std::endl;
+        break;
+    case ddl_double:
+        std::cout << getDouble() << std::endl;
+        break;
+    case ddl_string:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_ref:
+        std::cout << "Not supported" << std::endl;
+        break;
+    default:
+        break;
+    }
+}
+
+void Value::setNext( Value *next ) {
+    m_next = next;
+}
+
+Value *Value::getNext() const {
+    return m_next;
+}
+
+Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
+    if( type == Value::ddl_none || Value::ddl_types_max == type ) {
+        return ddl_nullptr;
+    }
+
+    Value *data = new Value;
+    data->m_type = type;
+    switch( type ) {
+        case Value::ddl_bool:
+            data->m_size = sizeof( bool );
+            break;
+        case Value::ddl_int8:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_int16:
+            data->m_size = sizeof( short );
+            break;
+        case Value::ddl_int32:
+            data->m_size = sizeof( int );
+            break;
+        case Value::ddl_int64:
+            data->m_size = sizeof( long );
+            break;
+        case Value::ddl_unsigned_int8:
+            data->m_size = sizeof( unsigned char );
+            break;
+        case Value::ddl_unsigned_int32:
+            data->m_size = sizeof( unsigned int );
+            break;
+        case Value::ddl_unsigned_int64:
+            data->m_size = sizeof( unsigned long );
+            break;
+        case Value::ddl_half:
+            data->m_size = sizeof( short );
+            break;
+        case Value::ddl_float:
+            data->m_size = sizeof( float );
+            break;
+        case Value::ddl_double:
+            data->m_size = sizeof( double );
+            break;
+        case Value::ddl_string:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_ref:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_none:
+        case Value::ddl_types_max:
+        default:
+            break;
+    }
+
+    if( data->m_size ) {
+        size_t len1( len );
+        if( Value::ddl_string == type ) {
+            len1++;
+        }
+        data->m_size *= len1;
+        data->m_data = new unsigned char[ data->m_size ];
+    }
+
+    return data;
+}
+
+void ValueAllocator::releasePrimData( Value **data ) {
+    if( !data ) {
+        return;
+    }
+
+    delete *data;
+    *data = ddl_nullptr;
+}
+
+END_ODDLPARSER_NS

+ 90 - 0
contrib/openddlparser/include/openddlparser/DDLNode.h

@@ -0,0 +1,90 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_DDLNODE_H_INC
+#define OPENDDLPARSER_DDLNODE_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <vector>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+class Value;
+class OpenDDLParser;
+
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+class DLL_ODDLPARSER_EXPORT DDLNode {
+public:
+    friend class OpenDDLParser;
+
+    typedef std::vector<DDLNode*> DllNodeList;
+
+public:
+    ~DDLNode();
+    void attachParent( DDLNode *parent );
+    void detachParent();
+    DDLNode *getParent() const;
+    const DllNodeList &getChildNodeList() const;
+    void setType( const std::string &name );
+    const std::string &getType() const;
+    void setName( const std::string &name );
+    const std::string &getName() const;
+    void setProperties( Property *prop );
+    Property *getProperties() const;
+    void setValue( Value *val );
+    Value *getValue() const;
+    void setDataArrayList( DataArrayList  *dtArrayList );
+    DataArrayList *getDataArrayList() const;
+    void setReferences( Reference  *refs );
+    Reference *getReferences() const;
+    static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr );
+
+private:
+    DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent = ddl_nullptr );
+    DDLNode();
+    DDLNode( const DDLNode & );
+    DDLNode &operator = ( const DDLNode & );
+    static void releaseNodes();
+
+private:
+    std::string m_type;
+    std::string m_name;
+    DDLNode *m_parent;
+    std::vector<DDLNode*> m_children;
+    Property *m_properties;
+    Value *m_value;
+    DataArrayList *m_dtArrayList;
+    Reference *m_references;
+    size_t m_idx;
+    static DllNodeList s_allocatedNodes;
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_DDLNODE_H_INC

+ 210 - 0
contrib/openddlparser/include/openddlparser/OpenDDLCommon.h

@@ -0,0 +1,210 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+#define OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+
+#include <cstddef>
+#include <vector>
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#   define TAG_DLL_EXPORT __declspec(dllexport)
+#   define TAG_DLL_IMPORT __declspec(dllimport )
+#   ifdef OPENDDLPARSER_BUILD
+#       define DLL_ODDLPARSER_EXPORT TAG_DLL_EXPORT
+#   else
+#       define DLL_ODDLPARSER_EXPORT TAG_DLL_IMPORT
+#   endif // OPENDDLPARSER_BUILD
+#   pragma warning( disable : 4251 )
+#else
+#   define DLL_ODDLPARSER_EXPORT
+#endif // _WIN32
+
+#define BEGIN_ODDLPARSER_NS namespace ODDLParser {
+#define END_ODDLPARSER_NS   }
+#define USE_ODDLPARSER_NS   using namespace ODDLParser;
+
+BEGIN_ODDLPARSER_NS
+
+#ifndef OPENDDL_NO_USE_CPP11
+#   define ddl_nullptr nullptr
+#else
+#   define ddl_nullptr NULL
+#endif // OPENDDL_NO_USE_CPP11
+
+class DDLNode;
+class Value;
+
+struct Name;
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+typedef char  int8;
+typedef short int16;
+typedef int   int32;
+typedef long  int64;
+typedef unsigned char  uint8;
+typedef unsigned short uint16;
+typedef unsigned int   uint32;
+typedef unsigned long  uint64;
+
+enum NameType {
+    GlobalName,
+    LocalName
+};
+
+struct Token {
+public:
+    Token( const char *token )
+    : m_token( token )
+    , m_size( 0 ){
+        if( ddl_nullptr != token ) {
+            m_size = strlen( m_token );
+        }
+    }
+    
+    ~Token() {
+        // empty
+    }
+
+    size_t length() const {
+        return m_size;
+    }
+
+    bool operator == ( const Token &rhs ) const {
+        if( m_size != rhs.m_size ) {
+            return false;
+        }
+
+        const int res( strncmp( m_token, rhs.m_token, m_size ) );
+        return ( res == 0 );
+    }
+
+private:
+    Token();
+    Token( const Token  & );
+    Token &operator = ( const Token & );
+
+private:
+    const char *m_token;
+    size_t m_size;
+};
+struct Name {
+    NameType    m_type;
+    Identifier *m_id;
+
+    Name( NameType type, Identifier *id )
+        : m_type( type )
+        , m_id( id ) {
+        // empty
+    }
+};
+
+struct Reference {
+    size_t   m_numRefs;
+    Name   **m_referencedName;
+
+    Reference()
+    : m_numRefs( 0 )
+    , m_referencedName( ddl_nullptr ) {
+        // empty
+    }
+     
+    Reference( size_t numrefs, Name **names )
+    : m_numRefs( numrefs )
+    , m_referencedName( ddl_nullptr ) {
+        m_referencedName = new Name *[ numrefs ];
+        for( size_t i = 0; i < numrefs; i++ ) {
+            Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id );
+            m_referencedName[ i ] = name;
+        }
+    }
+};
+
+struct Identifier {
+    size_t m_len;
+    char *m_buffer;
+
+    Identifier( size_t len, char buffer[] )
+        : m_len( len )
+        , m_buffer( buffer ) {
+        // empty
+    }
+};
+
+struct Property {
+    Identifier *m_id;
+    Value *m_primData;
+    Reference *m_ref;
+    Property *m_next;
+
+    Property( Identifier *id )
+        : m_id( id )
+        , m_primData( ddl_nullptr )
+        , m_ref( ddl_nullptr )
+        , m_next( ddl_nullptr ) {
+        // empty
+    }
+};
+
+struct DataArrayList {
+    size_t m_numItems;
+    Value *m_dataList;
+    DataArrayList *m_next;
+
+    DataArrayList()
+        : m_numItems( 0 )
+        , m_dataList( ddl_nullptr )
+        , m_next( ddl_nullptr ) {
+        // empty
+    }
+};
+
+struct Context {
+    DDLNode *m_root;
+
+    Context()
+        : m_root( ddl_nullptr ) {
+        // empty
+    }
+};
+
+struct BufferIt {
+    std::vector<char> m_buffer;
+    size_t m_idx;
+
+    BufferIt( const std::vector<char> &buffer )
+        : m_buffer( buffer )
+        , m_idx( 0 ) {
+        // empty
+    }
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+

+ 131 - 0
contrib/openddlparser/include/openddlparser/OpenDDLParser.h

@@ -0,0 +1,131 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSER_H_INC
+#define OPENDDLPARSER_OPENDDLPARSER_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParserUtils.h>
+#include <openddlparser/Value.h>
+
+#include <vector>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+class DDLNode;
+class Value;
+
+struct Identifier;
+struct Reference;
+struct Property;
+
+template<class T>
+inline
+T *lookForNextToken( T *in, T *end ) {
+    while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+        in++;
+    }
+    return in;
+}
+
+template<class T>
+inline
+T *getNextToken( T *in, T *end ) {
+    T *tmp( in );
+    while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+        in++;
+    }
+    if( tmp == in ) {
+        in++;
+    }
+    return in;
+}
+
+///	@brief  Defines the log severity.
+enum LogSeverity {
+    ddl_debug_msg = 0,  ///< Debug message, for debugging
+    ddl_info_msg,       ///< Info messages, normal mode
+    ddl_warn_msg,       ///< Parser warnings
+    ddl_error_msg       ///< Parser errors
+};
+
+class DLL_ODDLPARSER_EXPORT OpenDDLParser {
+public:
+    typedef void( *logCallback )( LogSeverity severity, const std::string &msg );
+
+public:
+    OpenDDLParser();
+    OpenDDLParser( char *buffer, size_t len );
+    ~OpenDDLParser();
+    void setLogCallback( logCallback callback );
+    logCallback getLogCallback() const;
+    void setBuffer( char *buffer, size_t len );
+    void setBuffer( const std::vector<char> &buffer );
+    const char *getBuffer() const;
+    size_t getBufferSize() const;
+    void clear();
+    bool parse();
+    char *parseNextNode( char *current, char *end );
+    char *parseHeader( char *in, char *end );
+    char *parseStructure( char *in, char *end );
+    char *parseStructureBody( char *in, char *end, bool &error );
+    void pushNode( DDLNode *node );
+    DDLNode *popNode();
+    DDLNode *top();
+    DDLNode *getRoot() const;
+    Context *getContext() const;
+
+public: // static parser helpers
+    static void normalizeBuffer( std::vector<char> &buffer );
+    static char *parseName( char *in, char *end, Name **name );
+    static char *parseIdentifier( char *in, char *end, Identifier **id );
+    static char *parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len );
+    static char *parseReference( char *in, char *end, std::vector<Name*> &names );
+    static char *parseBooleanLiteral( char *in, char *end, Value **boolean );
+    static char *parseIntegerLiteral( char *in, char *end, Value **integer, Value::ValueType integerType = Value::ddl_int32 );
+    static char *parseFloatingLiteral( char *in, char *end, Value **floating );
+    static char *parseStringLiteral( char *in, char *end, Value **stringData );
+    static char *parseHexaLiteral( char *in, char *end, Value **data );
+    static char *parseProperty( char *in, char *end, Property **prop );
+    static char *parseDataList( char *in, char *end, Value **data, size_t &numValues, Reference **refs, size_t &numRefs );
+    static char *parseDataArrayList( char *in, char *end, DataArrayList **dataList );
+    static const char *getVersion();
+
+private:
+    OpenDDLParser( const OpenDDLParser & );
+    OpenDDLParser &operator = ( const OpenDDLParser & );
+
+private:
+    logCallback m_logCallback;
+    std::vector<char> m_buffer;
+
+    typedef std::vector<DDLNode*> DDLNodeStack;
+    DDLNodeStack m_stack;
+    Context *m_context;
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_OPENDDLPARSER_H_INC

+ 250 - 0
contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h

@@ -0,0 +1,250 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
+#define OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+template<class T>
+inline
+bool isComment( T *in, T *end ) {
+    if( *in == '/' ) {
+        if( in + 1 != end ) {
+            if( *( in + 1 ) == '/' ) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+template<class T>
+inline
+bool isUpperCase( T in ) {
+    return ( in >= 'A' && in <= 'Z' );
+}
+
+template<class T>
+inline
+bool isLowerCase( T in ) {
+    return ( in >= 'a' && in <= 'z' );
+}
+
+template<class T> 
+inline 
+bool isSpace( const T in ) {
+    return ( ' ' == in || '\t' == in );
+}
+
+template<class T>
+inline
+bool isNewLine( const T in ) {
+    return ( '\n' == in || ( '\r' == in ) );
+}
+
+template<class T>
+inline
+bool isSeparator( T in ) {
+    if( isSpace( in ) || ',' == in || '{' == in || '}' == in || '[' == in ) {
+        return true;
+    }
+    return false;
+}
+
+static const unsigned char chartype_table[ 256 ] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 48-63
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112-127
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // > 127 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+template<class T>
+inline
+bool isNumeric( const T in ) {
+    return ( in >= '0' && in <= '9' );
+    //return ( chartype_table[in] );
+    /*if (in >= '0' &&  in <= '9' )
+    return true;
+
+    return false;*/
+}
+
+template<class T>
+inline
+bool isInteger( T *in, T *end ) {
+    if( in != end ) {
+        if( *in == '-' ) {
+            in++;
+        }
+    }
+
+    bool result( false );
+    while( '}' != *in && ',' != *in && !isSpace( *in ) && in != end ) {
+        result = isNumeric( *in );
+        if( !result ) {
+            break;
+        }
+        in++;
+    }
+
+    return result;
+}
+
+template<class T>
+inline
+bool isFloat( T *in, T *end ) {
+    if( in != end ) {
+        if( *in == '-' ) {
+            in++;
+        }
+    }
+
+    // check for <1>.0f
+    bool result( false );
+    while( !isSpace( *in ) && in != end ) {
+        if( *in == '.' ) {
+            result = true;
+            break;
+        }
+        result = isNumeric( *in );
+        if( !result ) {
+            return false;
+        }
+        in++;
+    }
+
+    // check for 1<.>0f
+    if( *in == '.' ) {
+        in++;
+    } else {
+        return false;
+    }
+
+    // check for 1.<0>f
+    while( !isSpace( *in ) && in != end && *in != ',' ) {
+        result = isNumeric( *in );
+        if( !result ) {
+            return false;
+        }
+        in++;
+    }
+
+    return result;
+}
+
+template<class T>
+inline
+bool isCharacter( const T in ) {
+    return ( ( in >= 'a' && in <= 'z' ) || ( in >= 'A' && in <= 'Z' ) );
+}
+
+template<class T>
+inline
+bool isStringLiteral( const T in ) {
+    return ( in == '\"' );
+}
+
+template<class T>
+inline
+bool isHexLiteral( T *in, T *end ) {
+    if( *in == '0' ) {
+        if( in + 1 != end ) {
+            if( *( in + 1 ) == 'x' || *( in + 1 ) == 'X' ) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+template<class T>
+inline
+bool isReference( T *in, T *end ) {
+    if( *in == 'r' ) {
+        if( *(in+1) == 'e' ) {
+            if( *(in+2) == 'f' ) {
+                if( ( in + 2 ) != end ) {
+                    return true;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+template<class T>
+inline
+bool isEndofLine( const T in ) {
+    return ( '\n' == in );
+}
+
+template<class T>
+inline
+static T *getNextSeparator( T *in, T *end ) {
+    while( !isSeparator( *in ) || in == end ) {
+        in++;
+    }
+    return in;
+}
+
+static const int ErrorHex2Decimal = 9999999;
+
+inline
+int hex2Decimal( char in ) {
+    if( isNumeric( in ) ) {
+        return ( in - 48 );
+    }
+    
+    char hexCodeLower( 'a' ), hexCodeUpper( 'A' );
+    for( int i = 0; i<16; i++ ) {
+        if( in == hexCodeLower + i || in == hexCodeUpper + i ) {
+            return ( i+10 );
+        }
+    }
+
+    return ErrorHex2Decimal;
+}
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC

+ 105 - 0
contrib/openddlparser/include/openddlparser/Value.h

@@ -0,0 +1,105 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_VALUE_H_INC
+#define OPENDDLPARSER_VALUE_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+///------------------------------------------------------------------------------------------------
+///	@brief  This class implements a value.
+///
+///	Values are used to store data types like boolean, integer, floats, double and many mode. To get
+///	an overview please check the enum VylueType ( @see Value::ValueType ).
+/// Values can be single items or lists of items. They are implemented as linked lists.
+///------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT Value {
+public:
+    ///	@brief  This enum describes the data type stored in the value.
+    enum ValueType {
+        ddl_none = -1,          ///< Nothing specified
+        ddl_bool = 0,           ///< A boolean type
+        ddl_int8,               ///< Integer type, 8 bytes
+        ddl_int16,              ///< Integer type, 16 bytes
+        ddl_int32,              ///< Integer type, 32 bytes
+        ddl_int64,              ///< Integer type, 64 bytes
+        ddl_unsigned_int8,      ///< Unsigned integer type, 8 bytes
+        ddl_unsigned_int16,     ///< Unsigned integer type, 16 bytes
+        ddl_unsigned_int32,     ///< Unsigned integer type, 32 bytes
+        ddl_unsigned_int64,     ///< Unsigned integer type, 64 bytes
+        ddl_half,               
+        ddl_float,
+        ddl_double,
+        ddl_string,
+        ddl_ref,
+        ddl_types_max
+    };
+
+    Value();
+    ~Value();
+    void setBool( bool value );
+    bool getBool();
+    void setInt8( int8 value );
+    int8 getInt8();
+    void setInt16( int16 value );
+    int16 getInt16();
+    void setInt32( int32 value );
+    int32 getInt32();
+    void setInt64( int64 value );
+    int64 getInt64();
+    void setUnsignedInt8( uint8 value );
+    uint8 getUnsignedInt8() const;
+    void setUnsignedInt16( uint16 value );
+    uint16 getUnsignedInt16() const;
+    void setUnsignedInt32( uint32 value );
+    uint32 getUnsignedInt32() const;
+    void setUnsignedInt64( uint64 value );
+    uint64 getUnsignedInt64() const;
+    void setFloat( float value );
+    float getFloat() const;
+    void setDouble( double value );
+    double getDouble() const;
+    void setString( const std::string &str );
+    const char *getString() const;
+    void dump();
+    void setNext( Value *next );
+    Value *getNext() const;
+
+    ValueType m_type;
+    size_t m_size;
+    unsigned char *m_data;
+    Value *m_next;
+};
+
+struct DLL_ODDLPARSER_EXPORT ValueAllocator {
+    static Value *allocPrimData( Value::ValueType type, size_t len = 1 );
+    static void releasePrimData( Value **data );
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_VALUE_H_INC

+ 46 - 46
include/assimp/Compiler/pushpack1.h

@@ -1,46 +1,46 @@
-
-
-// ===============================================================================
-// May be included multiple times - sets structure packing to 1 
-// for all supported compilers. #include <poppack1.h> reverts the changes.
-//
-// Currently this works on the following compilers:
-// MSVC 7,8,9
-// GCC
-// BORLAND (complains about 'pack state changed but not reverted', but works)
-// Clang
-//
-//
-// USAGE:
-//
-// struct StructToBePacked {
-// } PACK_STRUCT;
-//
-// ===============================================================================
-
-#ifdef AI_PUSHPACK_IS_DEFINED
-#	error poppack1.h must be included after pushpack1.h
-#endif
-
-#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
-#	pragma pack(push,1)
-#	define PACK_STRUCT
-#elif defined( __GNUC__ )
-#	if defined(__clang__)
-#		define PACK_STRUCT	__attribute__((__packed__))
-#	else
-#		define PACK_STRUCT	__attribute__((gcc_struct, __packed__))
-#	endif
-#else
-#	error Compiler not supported
-#endif
-
-#if defined(_MSC_VER)
-
-// C4103: Packing was changed after the inclusion of the header, propably missing #pragma pop
-#	pragma warning (disable : 4103) 
-#endif
-
-#define AI_PUSHPACK_IS_DEFINED
-
-
+
+
+// ===============================================================================
+// May be included multiple times - sets structure packing to 1 
+// for all supported compilers. #include <poppack1.h> reverts the changes.
+//
+// Currently this works on the following compilers:
+// MSVC 7,8,9
+// GCC
+// BORLAND (complains about 'pack state changed but not reverted', but works)
+// Clang
+//
+//
+// USAGE:
+//
+// struct StructToBePacked {
+// } PACK_STRUCT;
+//
+// ===============================================================================
+
+#ifdef AI_PUSHPACK_IS_DEFINED
+#	error poppack1.h must be included after pushpack1.h
+#endif
+
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
+#	pragma pack(push,1)
+#	define PACK_STRUCT
+#elif defined( __GNUC__ )
+#	if !defined(HOST_MINGW)
+#		define PACK_STRUCT	__attribute__((__packed__))
+#	else
+#		define PACK_STRUCT	__attribute__((gcc_struct, __packed__))
+#	endif
+#else
+#	error Compiler not supported
+#endif
+
+#if defined(_MSC_VER)
+
+// C4103: Packing was changed after the inclusion of the header, propably missing #pragma pop
+#	pragma warning (disable : 4103) 
+#endif
+
+#define AI_PUSHPACK_IS_DEFINED
+
+

+ 185 - 9
include/assimp/Exporter.hpp

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 
 
 #include "cexport.h"
 #include "cexport.h"
+#include <map>
 
 
 namespace Assimp	{
 namespace Assimp	{
 	class ExporterPimpl;
 	class ExporterPimpl;
@@ -72,6 +73,9 @@ namespace Assimp	{
  * #ExportToBlob is especially useful if you intend to work 
  * #ExportToBlob is especially useful if you intend to work 
  * with the data in-memory. 
  * with the data in-memory. 
 */
 */
+
+class ASSIMP_API ExportProperties;
+
 class ASSIMP_API Exporter
 class ASSIMP_API Exporter
 	// TODO: causes good ol' base class has no dll interface warning
 	// TODO: causes good ol' base class has no dll interface warning
 //#ifdef __cplusplus
 //#ifdef __cplusplus
@@ -81,7 +85,7 @@ class ASSIMP_API Exporter
 public:
 public:
 
 
 	/** Function pointer type of a Export worker function */
 	/** Function pointer type of a Export worker function */
-	typedef void (*fpExportFunc)(const char*,IOSystem*, const aiScene*);
+	typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 
 
 	/** Internal description of an Assimp export format option */
 	/** Internal description of an Assimp export format option */
 	struct ExportFormatEntry
 	struct ExportFormatEntry
@@ -171,8 +175,8 @@ public:
 	*   Any IO handlers set via #SetIOHandler are ignored here.
 	*   Any IO handlers set via #SetIOHandler are ignored here.
 	* @note Use aiCopyScene() to get a modifiable copy of a previously
 	* @note Use aiCopyScene() to get a modifiable copy of a previously
 	*   imported scene. */
 	*   imported scene. */
-	const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u );
-	inline const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u );
+	const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+	inline const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
 
 
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
@@ -208,8 +212,8 @@ public:
 	 * @return AI_SUCCESS if everything was fine. 
 	 * @return AI_SUCCESS if everything was fine. 
 	 * @note Use aiCopyScene() to get a modifiable copy of a previously
 	 * @note Use aiCopyScene() to get a modifiable copy of a previously
 	 *   imported scene.*/
 	 *   imported scene.*/
-	aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u);
-	inline aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath,  unsigned int pPreprocessing = 0u);
+	aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+	inline aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath,  unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
 
 
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
@@ -309,16 +313,188 @@ protected:
 };
 };
 
 
 
 
+class ASSIMP_API ExportProperties
+{
+public:
+	// Data type to store the key hash
+	typedef unsigned int KeyType;
+	
+	// typedefs for our four configuration maps.
+	// We don't need more, so there is no need for a generic solution
+	typedef std::map<KeyType, int> IntPropertyMap;
+	typedef std::map<KeyType, float> FloatPropertyMap;
+	typedef std::map<KeyType, std::string> StringPropertyMap;
+	typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
+
+public:
+
+	/** Standard constructor
+	* @see ExportProperties()
+	*/
+
+	ExportProperties();
+
+	// -------------------------------------------------------------------
+	/** Copy constructor.
+	 * 
+	 * This copies the configuration properties of another ExportProperties.
+	 * @see ExportProperties(const ExportProperties& other)
+	 */
+	ExportProperties(const ExportProperties& other);
+
+	// -------------------------------------------------------------------
+	/** Set an integer configuration property.
+	 * @param szName Name of the property. All supported properties
+	 *   are defined in the aiConfig.g header (all constants share the
+	 *   prefix AI_CONFIG_XXX and are simple strings).
+	 * @param iValue New value of the property
+	 * @param bWasExisting Optional pointer to receive true if the
+	 *   property was set before. The new value replaces the previous value
+	 *   in this case.
+	 * @note Property of different types (float, int, string ..) are kept
+	 *   on different stacks, so calling SetPropertyInteger() for a 
+	 *   floating-point property has no effect - the loader will call
+	 *   GetPropertyFloat() to read the property, but it won't be there.
+	 */
+	void SetPropertyInteger(const char* szName, int iValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Set a boolean configuration property. Boolean properties
+	 *  are stored on the integer stack internally so it's possible
+	 *  to set them via #SetPropertyBool and query them with
+	 *  #GetPropertyBool and vice versa.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyBool(const char* szName, bool value, bool* bWasExisting = NULL)	{
+		SetPropertyInteger(szName,value,bWasExisting);
+	}
+
+	// -------------------------------------------------------------------
+	/** Set a floating-point configuration property.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyFloat(const char* szName, float fValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Set a string configuration property.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyString(const char* szName, const std::string& sValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Set a matrix configuration property.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Get a configuration property.
+	 * @param szName Name of the property. All supported properties
+	 *   are defined in the aiConfig.g header (all constants share the
+	 *   prefix AI_CONFIG_XXX).
+	 * @param iErrorReturn Value that is returned if the property 
+	 *   is not found. 
+	 * @return Current value of the property
+	 * @note Property of different types (float, int, string ..) are kept
+	 *   on different lists, so calling SetPropertyInteger() for a 
+	 *   floating-point property has no effect - the loader will call
+	 *   GetPropertyFloat() to read the property, but it won't be there.
+	 */
+	int GetPropertyInteger(const char* szName, 
+		int iErrorReturn = 0xffffffff) const;
+
+	// -------------------------------------------------------------------
+	/** Get a boolean configuration property. Boolean properties
+	 *  are stored on the integer stack internally so it's possible
+	 *  to set them via #SetPropertyBool and query them with
+	 *  #GetPropertyBool and vice versa.
+	 * @see GetPropertyInteger()
+	 */
+	bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const {
+		return GetPropertyInteger(szName,bErrorReturn)!=0;
+	}
+
+	// -------------------------------------------------------------------
+	/** Get a floating-point configuration property
+	 * @see GetPropertyInteger()
+	 */
+	float GetPropertyFloat(const char* szName, 
+		float fErrorReturn = 10e10f) const;
+
+	// -------------------------------------------------------------------
+	/** Get a string configuration property
+	 *
+	 *  The return value remains valid until the property is modified.
+	 * @see GetPropertyInteger()
+	 */
+	const std::string GetPropertyString(const char* szName,
+		const std::string& sErrorReturn = "") const;
+
+	// -------------------------------------------------------------------
+	/** Get a matrix configuration property
+	 *
+	 *  The return value remains valid until the property is modified.
+	 * @see GetPropertyInteger()
+	 */
+	const aiMatrix4x4 GetPropertyMatrix(const char* szName,
+		const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
+
+	// -------------------------------------------------------------------
+	/** Determine a integer configuration property has been set.
+	* @see HasPropertyInteger()
+	 */
+	bool HasPropertyInteger(const char* szName) const;
+
+	/** Determine a boolean configuration property has been set.
+	* @see HasPropertyBool()
+	 */
+	bool HasPropertyBool(const char* szName) const;
+
+	/** Determine a boolean configuration property has been set.
+	* @see HasPropertyFloat()
+	 */
+	bool HasPropertyFloat(const char* szName) const;
+
+	/** Determine a String configuration property has been set.
+	* @see HasPropertyString()
+	 */
+	bool HasPropertyString(const char* szName) const;
+
+	/** Determine a Matrix configuration property has been set.
+	* @see HasPropertyMatrix()
+	 */
+	bool HasPropertyMatrix(const char* szName) const;
+
+protected:
+
+	/** List of integer properties */
+	IntPropertyMap mIntProperties;
+
+	/** List of floating-point properties */
+	FloatPropertyMap mFloatProperties;
+
+	/** List of string properties */
+	StringPropertyMap mStringProperties;
+
+	/** List of Matrix properties */
+	MatrixPropertyMap mMatrixProperties;
+};
+
+
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing ) 
+inline const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing, const ExportProperties* pProperties) 
 {
 {
-	return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing);
+	return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing, pProperties);
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing )
+inline aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
 {
 {
-	return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing);
+	return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing, pProperties);
 }
 }
 
 
 } // namespace Assimp
 } // namespace Assimp

+ 11 - 0
include/assimp/config.h

@@ -879,4 +879,15 @@ enum aiComponent
 
 
 #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
 #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
 
 
+
+// ---------- All the Export defines ------------
+
+/** @brief Specifies the xfile use double for real values of float
+ *
+ * Property type: Bool. Default value: false.
+ */
+
+#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
+
+
 #endif // !! AI_CONFIG_H_INC
 #endif // !! AI_CONFIG_H_INC

+ 53 - 44
port/jassimp/build.xml

@@ -1,45 +1,54 @@
 <project name="jassimp" basedir="." default="all">
 <project name="jassimp" basedir="." default="all">
-  <property name="native-src.dir" value="jassimp-native/src" />
-  <property name="src.dir" value="jassimp/src" />
-  <property name="jassimp.lwjgl-src.dir" value="jassimp.lwjgl/src" />
-  <property name="build.dir" value="jassimp/bin" />
-  <property name="dist.dir" value="dist" />
-  <property name="doc.dir" value="doc" />
-  
-  <path id="classpath">
-  </path>
-
-  <target name="compile">
-    <delete dir="${build.dir}" />
-    <mkdir dir="${build.dir}" />
-    <javac classpathref="classpath" destdir="${build.dir}" srcdir="${src.dir}"
-      source="1.6" target="1.6" includeantruntime="false">
-    </javac>
-  </target>
-
-  <target name="jni_header">
-    <mkdir dir="${native-src.dir}" />
-    <javah outputfile="${native-src.dir}/jassimp.h" force="yes">
-      <classpath>
-        <pathelement path="${build.dir}" />
-      </classpath>
-      <class name="jassimp.Jassimp" />
-    </javah>
-  </target>
-  
-  <target name="package" depends="compile">
-    <jar destfile="${dist.dir}/jassimp.jar" basedir="${build.dir}">
-    </jar>
-  </target>
-  
-  
-  <target name="doc">
-    <delete dir="${doc.dir}" />
-    <javadoc access="public" author="false" destdir="${doc.dir}"
-      sourcepath="${src.dir}">
-    </javadoc>
-  </target>
-  
-  <target name="all" depends="package, doc">
-  </target>
-</project>
+	<property name="native-src.dir" value="jassimp-native/src" />
+	<property name="src.dir" value="jassimp/src" />
+	<property name="jassimp.lwjgl-src.dir" value="jassimp.lwjgl/src" />
+	<property name="build.dir" value="jassimp/bin" />
+	<property name="dist.dir" value="dist" />
+	<property name="doc.dir" value="doc" />
+	<property environment="env"/>
+	<property name="ndk.dir" value="${env.NDK_HOME}" />
+	<property name="my.dir" value="${env.PWD}" />
+
+	<path id="classpath">
+	</path>
+
+	<target name="compile">
+		<delete dir="${build.dir}" />
+		<mkdir dir="${build.dir}" />
+		<javac classpathref="classpath" destdir="${build.dir}" srcdir="${src.dir}"
+			source="1.6" target="1.6" includeantruntime="false">
+		</javac>
+	</target>
+
+	<target name="jni_header">
+		<mkdir dir="${native-src.dir}" />
+		<javah outputfile="${native-src.dir}/jassimp.h" force="yes">
+			<classpath>
+				<pathelement path="${build.dir}" />
+			</classpath>
+			<class name="jassimp.Jassimp" />
+		</javah>
+	</target>
+
+	<target name="ndk-jni" depends="package">
+		<exec executable="${ndk.dir}/ndk-build">
+			<arg line="all NDK_PROJECT_PATH=${my.dir}/workspaces/Android-NDK"/>
+		</exec>
+	</target>
+
+	<target name="package" depends="compile">
+		<jar destfile="${dist.dir}/jassimp.jar" basedir="${build.dir}">
+		</jar>
+	</target>
+
+
+	<target name="doc">
+		<delete dir="${doc.dir}" />
+		<javadoc access="public" author="false" destdir="${doc.dir}"
+			sourcepath="${src.dir}">
+		</javadoc>
+	</target>
+
+	<target name="all" depends="package, doc">
+	</target>
+</project>

+ 13 - 0
port/jassimp/jassimp-native/Android.mk

@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := jassimp
+LOCAL_SRC_FILES :=  src/jassimp.cpp
+
+LOCAL_CFLAGS += -DJNI_LOG
+
+#LOCAL_STATIC_LIBRARIES := assimp_static
+LOCAL_SHARED_LIBRARIES := assimp
+LOCAL_LDLIBS    := -llog
+
+include $(BUILD_SHARED_LIBRARY)

+ 118 - 28
port/jassimp/jassimp-native/src/jassimp.cpp

@@ -5,12 +5,16 @@
 
 
 
 
 #ifdef JNI_LOG
 #ifdef JNI_LOG
+#ifdef ANDROID
+#include <android/log.h>
+#define lprintf(...) __android_log_print(ANDROID_LOG_VERBOSE, __func__, __VA_ARGS__)
+#else
 #define lprintf(...) printf (__VA_ARGS__)
 #define lprintf(...) printf (__VA_ARGS__)
+#endif /* ANDROID */
 #else
 #else
 #define lprintf
 #define lprintf
 #endif
 #endif
 
 
-
 static bool createInstance(JNIEnv *env, const char* className, jobject& newInstance)
 static bool createInstance(JNIEnv *env, const char* className, jobject& newInstance)
 {
 {
 	jclass clazz = env->FindClass(className);
 	jclass clazz = env->FindClass(className);
@@ -30,6 +34,7 @@ static bool createInstance(JNIEnv *env, const char* className, jobject& newInsta
 	}
 	}
 
 
 	newInstance = env->NewObject(clazz, ctr_id);
 	newInstance = env->NewObject(clazz, ctr_id);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == newInstance) 
 	if (NULL == newInstance) 
 	{
 	{
@@ -41,7 +46,7 @@ static bool createInstance(JNIEnv *env, const char* className, jobject& newInsta
 }
 }
 
 
 
 
-static bool createInstance(JNIEnv *env, const char* className, const char* signature, const jvalue* params, jobject& newInstance)
+static bool createInstance(JNIEnv *env, const char* className, const char* signature,/* const*/ jvalue* params, jobject& newInstance)
 {
 {
 	jclass clazz = env->FindClass(className);
 	jclass clazz = env->FindClass(className);
 
 
@@ -60,6 +65,7 @@ static bool createInstance(JNIEnv *env, const char* className, const char* signa
 	}
 	}
 
 
 	newInstance = env->NewObjectA(clazz, ctr_id, params);
 	newInstance = env->NewObjectA(clazz, ctr_id, params);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == newInstance) 
 	if (NULL == newInstance) 
 	{
 	{
@@ -82,6 +88,7 @@ static bool getField(JNIEnv *env, jobject object, const char* fieldName, const c
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -106,6 +113,7 @@ static bool setIntField(JNIEnv *env, jobject object, const char* fieldName, jint
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "I");
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "I");
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -130,6 +138,7 @@ static bool setFloatField(JNIEnv *env, jobject object, const char* fieldName, jf
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "F");
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "F");
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -154,6 +163,7 @@ static bool setObjectField(JNIEnv *env, jobject object, const char* fieldName, c
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -192,7 +202,7 @@ static bool getStaticField(JNIEnv *env, const char* className, const char* field
 
 
 
 
 static bool call(JNIEnv *env, jobject object, const char* typeName, const char* methodName, 
 static bool call(JNIEnv *env, jobject object, const char* typeName, const char* methodName, 
-	const char* signature, const jvalue* params)
+	const char* signature,/* const*/ jvalue* params)
 {
 {
 	jclass clazz = env->FindClass(typeName);
 	jclass clazz = env->FindClass(typeName);
 
 
@@ -203,6 +213,7 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
 	}
 	}
 
 
 	jmethodID mid = env->GetMethodID(clazz, methodName, signature);
 	jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == mid)
 	if (NULL == mid)
 	{
 	{
@@ -210,6 +221,27 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
 		return false;
 		return false;
 	}
 	}
 
 
+	jboolean jReturnValue = env->CallBooleanMethod(object, mid, params[0].l);
+
+	return (bool)jReturnValue;
+}
+static bool callv(JNIEnv *env, jobject object, const char* typeName,
+		const char* methodName, const char* signature,/* const*/ jvalue* params) {
+	jclass clazz = env->FindClass(typeName);
+
+	if (NULL == clazz) {
+		lprintf("could not find class %s\n", typeName);
+		return false;
+	}
+
+	jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+	env->DeleteLocalRef(clazz);
+
+	if (NULL == mid) {
+		lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+		return false;
+	}
+
 	env->CallVoidMethodA(object, mid, params);
 	env->CallVoidMethodA(object, mid, params);
 
 
 	return true;
 	return true;
@@ -217,7 +249,7 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
 
 
 
 
 static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName, 
 static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName, 
-	const char* signature, const jvalue* params, jobject& returnValue)
+	const char* signature,/* const*/ jvalue* params, jobject& returnValue)
 {
 {
 	jclass clazz = env->FindClass(typeName);
 	jclass clazz = env->FindClass(typeName);
 
 
@@ -252,7 +284,7 @@ static bool copyBuffer(JNIEnv *env, jobject jMesh, const char* jBufferName, void
 
 
 	if (env->GetDirectBufferCapacity(jBuffer) != size)
 	if (env->GetDirectBufferCapacity(jBuffer) != size)
 	{
 	{
-		lprintf("invalid direct buffer, expected %u, got %u\n", size, env->GetDirectBufferCapacity(jBuffer));
+		lprintf("invalid direct buffer, expected %u, got %llu\n", size, env->GetDirectBufferCapacity(jBuffer));
 		return false;
 		return false;
 	}
 	}
 
 
@@ -283,7 +315,7 @@ static bool copyBufferArray(JNIEnv *env, jobject jMesh, const char* jBufferName,
 
 
 	if (env->GetDirectBufferCapacity(jBuffer) != size)
 	if (env->GetDirectBufferCapacity(jBuffer) != size)
 	{
 	{
-		lprintf("invalid direct buffer, expected %u, got %u\n", size, env->GetDirectBufferCapacity(jBuffer));
+		lprintf("invalid direct buffer, expected %u, got %llu\n", size, env->GetDirectBufferCapacity(jBuffer));
 		return false;
 		return false;
 	}
 	}
 
 
@@ -338,7 +370,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		/* set general mesh data in java */
 		/* set general mesh data in java */
 		jvalue setTypesParams[1];
 		jvalue setTypesParams[1];
 		setTypesParams[0].i = cMesh->mPrimitiveTypes;
 		setTypesParams[0].i = cMesh->mPrimitiveTypes;
-		if (!call(env, jMesh, "jassimp/AiMesh", "setPrimitiveTypes", "(I)V", setTypesParams))
+		if (!callv(env, jMesh, "jassimp/AiMesh", "setPrimitiveTypes", "(I)V", setTypesParams))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -380,7 +412,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		allocateBuffersParams[1].i = cMesh->mNumFaces;
 		allocateBuffersParams[1].i = cMesh->mNumFaces;
 		allocateBuffersParams[2].z = isPureTriangle;
 		allocateBuffersParams[2].z = isPureTriangle;
 		allocateBuffersParams[3].i = (jint) faceBufferSize;
 		allocateBuffersParams[3].i = (jint) faceBufferSize;
-		if (!call(env, jMesh, "jassimp/AiMesh", "allocateBuffers", "(IIZI)V", allocateBuffersParams))
+		if (!callv(env, jMesh, "jassimp/AiMesh", "allocateBuffers", "(IIZI)V", allocateBuffersParams))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -470,7 +502,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 0;
 			allocateDataChannelParams[0].i = 0;
 			allocateDataChannelParams[1].i = 0;
 			allocateDataChannelParams[1].i = 0;
-			if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+			if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 			{
 			{
 				lprintf("could not allocate normal data channel\n");
 				lprintf("could not allocate normal data channel\n");
 				return false;
 				return false;
@@ -491,7 +523,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 1;
 			allocateDataChannelParams[0].i = 1;
 			allocateDataChannelParams[1].i = 0;
 			allocateDataChannelParams[1].i = 0;
-			if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+			if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 			{
 			{
 				lprintf("could not allocate tangents data channel\n");
 				lprintf("could not allocate tangents data channel\n");
 				return false;
 				return false;
@@ -512,7 +544,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 2;
 			allocateDataChannelParams[0].i = 2;
 			allocateDataChannelParams[1].i = 0;
 			allocateDataChannelParams[1].i = 0;
-			if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+			if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 			{
 			{
 				lprintf("could not allocate bitangents data channel\n");
 				lprintf("could not allocate bitangents data channel\n");
 				return false;
 				return false;
@@ -535,7 +567,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				jvalue allocateDataChannelParams[2];
 				jvalue allocateDataChannelParams[2];
 				allocateDataChannelParams[0].i = 3;
 				allocateDataChannelParams[0].i = 3;
 				allocateDataChannelParams[1].i = c;
 				allocateDataChannelParams[1].i = c;
-				if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+				if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 				{
 				{
 					lprintf("could not allocate colorset data channel\n");
 					lprintf("could not allocate colorset data channel\n");
 					return false;
 					return false;
@@ -574,7 +606,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				}
 				}
 
 
 				allocateDataChannelParams[1].i = c;
 				allocateDataChannelParams[1].i = c;
-				if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+				if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 				{
 				{
 					lprintf("could not allocate texture coordinates data channel\n");
 					lprintf("could not allocate texture coordinates data channel\n");
 					return false;
 					return false;
@@ -671,7 +703,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapParams[0].l = jMatrixArr;
 				wrapParams[0].l = jMatrixArr;
 				jobject jMatrix;
 				jobject jMatrix;
 				
 				
-				if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapMatrix", "([F)Ljava/lang/Object;", wrapParams, jMatrix)) 
+				if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapParams, jMatrix))
 				{
 				{
 					return false;
 					return false;
 				}
 				}
@@ -701,6 +733,8 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				}
 				}
 			}
 			}
 		}
 		}
+		env->DeleteLocalRef(jMeshes);
+		env->DeleteLocalRef(jMesh);
 	}
 	}
 
 
 	return true;
 	return true;
@@ -719,7 +753,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
 	wrapMatParams[0].l = jMatrixArr;
 	wrapMatParams[0].l = jMatrixArr;
 	jobject jMatrix;
 	jobject jMatrix;
 				
 				
-	if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix)) 
+	if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix))
 	{
 	{
 		return false;
 		return false;
 	}
 	}
@@ -749,7 +783,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
 	wrapNodeParams[2].l = jMeshrefArr;
 	wrapNodeParams[2].l = jMeshrefArr;
 	wrapNodeParams[3].l = jNodeName;
 	wrapNodeParams[3].l = jNodeName;
 	jobject jNode;
 	jobject jNode;
-	if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapSceneNode", 
+	if (!callStaticObject(env, "jassimp/Jassimp", "wrapSceneNode",
 		"(Ljava/lang/Object;Ljava/lang/Object;[ILjava/lang/String;)Ljava/lang/Object;", wrapNodeParams, jNode)) 
 		"(Ljava/lang/Object;Ljava/lang/Object;[ILjava/lang/String;)Ljava/lang/Object;", wrapNodeParams, jNode)) 
 	{
 	{
 		return false;
 		return false;
@@ -805,7 +839,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 	{
 	{
 		const aiMaterial* cMaterial = cScene->mMaterials[m];
 		const aiMaterial* cMaterial = cScene->mMaterials[m];
 
 
-		lprintf("converting material ...\n", m);
+		lprintf("converting material %d ...\n", m);
 
 
 		jobject jMaterial = NULL;
 		jobject jMaterial = NULL;
 
 
@@ -842,7 +876,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			setNumberParams[0].i = ttInd;
 			setNumberParams[0].i = ttInd;
 			setNumberParams[1].i = num;
 			setNumberParams[1].i = num;
 
 
-			if (!call(env, jMaterial, "jassimp/AiMaterial", "setTextureNumber", "(II)V", setNumberParams))
+			if (!callv(env, jMaterial, "jassimp/AiMaterial", "setTextureNumber", "(II)V", setNumberParams))
 			{
 			{
 				return false;
 				return false;
 			}
 			}
@@ -880,7 +914,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapColorParams[0].f = ((float*) cProperty->mData)[0];
 				wrapColorParams[0].f = ((float*) cProperty->mData)[0];
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
-				if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jData)) 
+				if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jData))
 				{
 				{
 					return false;
 					return false;
 				}
 				}
@@ -905,7 +939,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
 				wrapColorParams[3].f = ((float*) cProperty->mData)[3];
 				wrapColorParams[3].f = ((float*) cProperty->mData)[3];
-				if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor4", "(FFFF)Ljava/lang/Object;", wrapColorParams, jData)) 
+				if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor4", "(FFFF)Ljava/lang/Object;", wrapColorParams, jData))
 				{
 				{
 					return false;
 					return false;
 				}
 				}
@@ -1137,7 +1171,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorDiffuse.g;
 		wrapColorParams[1].f = cLight->mColorDiffuse.g;
 		wrapColorParams[2].f = cLight->mColorDiffuse.b;
 		wrapColorParams[2].f = cLight->mColorDiffuse.b;
 		jobject jDiffuse;
 		jobject jDiffuse;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jDiffuse)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jDiffuse))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1146,7 +1180,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorSpecular.g;
 		wrapColorParams[1].f = cLight->mColorSpecular.g;
 		wrapColorParams[2].f = cLight->mColorSpecular.b;
 		wrapColorParams[2].f = cLight->mColorSpecular.b;
 		jobject jSpecular;
 		jobject jSpecular;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jSpecular)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jSpecular))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1155,7 +1189,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorAmbient.g;
 		wrapColorParams[1].f = cLight->mColorAmbient.g;
 		wrapColorParams[2].f = cLight->mColorAmbient.b;
 		wrapColorParams[2].f = cLight->mColorAmbient.b;
 		jobject jAmbient;
 		jobject jAmbient;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jAmbient)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jAmbient))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1167,7 +1201,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		jobject jPosition;
 		jobject jPosition;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jPosition)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jPosition))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1176,7 +1210,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		jobject jDirection;
 		jobject jDirection;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jDirection)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jDirection))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1242,7 +1276,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mPosition.y;
 		wrapPositionParams[1].f = cCamera->mPosition.y;
 		wrapPositionParams[2].f = cCamera->mPosition.z;
 		wrapPositionParams[2].f = cCamera->mPosition.z;
 		jobject jPosition;
 		jobject jPosition;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jPosition)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jPosition))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1251,7 +1285,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mUp.y;
 		wrapPositionParams[1].f = cCamera->mUp.y;
 		wrapPositionParams[2].f = cCamera->mUp.z;
 		wrapPositionParams[2].f = cCamera->mUp.z;
 		jobject jUp;
 		jobject jUp;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jUp)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jUp))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1260,7 +1294,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mLookAt.y;
 		wrapPositionParams[1].f = cCamera->mLookAt.y;
 		wrapPositionParams[2].f = cCamera->mLookAt.z;
 		wrapPositionParams[2].f = cCamera->mLookAt.z;
 		jobject jLookAt;
 		jobject jLookAt;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jLookAt)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jLookAt))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1306,6 +1340,62 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 }
 }
 
 
 
 
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getVKeysize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(aiVectorKey);
+	return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getQKeysize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(aiQuatKey);
+	return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getV3Dsize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(aiVector3D);
+	return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getfloatsize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(float);
+	return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getintsize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(int);
+	return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getuintsize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(unsigned int);
+	return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getdoublesize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(double);
+	return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getlongsize
+  (JNIEnv *env, jclass jClazz)
+{
+	const int res = sizeof(long);
+	return res;
+}
+
 JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
 JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
   (JNIEnv *env, jclass jClazz)
   (JNIEnv *env, jclass jClazz)
 {
 {

+ 17 - 0
port/jassimp/jassimp-native/src/jassimp.h

@@ -7,6 +7,23 @@
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getVKeysize
+  (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getQKeysize
+  (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getV3Dsize
+  (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getfloatsize
+  (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getintsize
+  (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getuintsize
+  (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getdoublesize
+  (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getlongsize
+  (JNIEnv *, jclass);
+
 /*
 /*
  * Class:     jassimp_Jassimp
  * Class:     jassimp_Jassimp
  * Method:    getErrorString
  * Method:    getErrorString

+ 8 - 4
port/jassimp/jassimp/src/jassimp/AiMesh.java

@@ -140,13 +140,17 @@ public final class AiMesh {
     /**
     /**
      * Number of bytes per float value.
      * Number of bytes per float value.
      */
      */
-    private static final int SIZEOF_FLOAT = 4;
-    
-    
+    private static final int SIZEOF_FLOAT = Jassimp.NATIVE_FLOAT_SIZE;
+        
     /**
     /**
      * Number of bytes per int value.
      * Number of bytes per int value.
      */
      */
-    private static final int SIZEOF_INT = 4;
+    private static final int SIZEOF_INT = Jassimp.NATIVE_INT_SIZE;
+
+    /**
+     * Size of an AiVector3D in the native world.
+     */
+    private static final int SIZEOF_V3D = Jassimp.NATIVE_AIVEKTOR3D_SIZE;
     
     
     
     
     /**
     /**

+ 10 - 11
port/jassimp/jassimp/src/jassimp/AiNodeAnim.java

@@ -3,7 +3,7 @@
 Open Asset Import Library - Java Binding (jassimp)
 Open Asset Import Library - Java Binding (jassimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -68,19 +68,19 @@ import java.nio.ByteOrder;
  */
  */
 public final class AiNodeAnim {
 public final class AiNodeAnim {
     /**
     /**
-     * Size of one position key entry (includes padding).
+     * Size of one position key entry.
      */
      */
-    private static final int POS_KEY_SIZE = 24;
+    private static final int POS_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE;
     
     
     /**
     /**
      * Size of one rotation key entry.
      * Size of one rotation key entry.
      */
      */
-    private static final int ROT_KEY_SIZE = 24;
+    private static final int ROT_KEY_SIZE = Jassimp.NATIVE_AIQUATKEY_SIZE;
     
     
     /**
     /**
-     * Size of one scaling key entry (includes padding).
+     * Size of one scaling key entry.
      */
      */
-    private static final int SCALE_KEY_SIZE = 24;
+    private static final int SCALE_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE;
     
     
     
     
     /**
     /**
@@ -103,14 +103,13 @@ public final class AiNodeAnim {
         m_preState = AiAnimBehavior.fromRawValue(preBehavior);
         m_preState = AiAnimBehavior.fromRawValue(preBehavior);
         m_postState = AiAnimBehavior.fromRawValue(postBehavior);
         m_postState = AiAnimBehavior.fromRawValue(postBehavior);
         
         
-        /* c data is padded -> 24 bytes with 20 bytes data */
         m_posKeys = ByteBuffer.allocateDirect(numPosKeys * POS_KEY_SIZE);
         m_posKeys = ByteBuffer.allocateDirect(numPosKeys * POS_KEY_SIZE);
         m_posKeys.order(ByteOrder.nativeOrder());
         m_posKeys.order(ByteOrder.nativeOrder());
         
         
-        m_rotKeys = ByteBuffer.allocateDirect(numRotKeys * 24);
+        m_rotKeys = ByteBuffer.allocateDirect(numRotKeys * ROT_KEY_SIZE);
         m_rotKeys.order(ByteOrder.nativeOrder());
         m_rotKeys.order(ByteOrder.nativeOrder());
         
         
-        m_scaleKeys = ByteBuffer.allocateDirect(numScaleKeys * 24);
+        m_scaleKeys = ByteBuffer.allocateDirect(numScaleKeys * SCALE_KEY_SIZE);
         m_scaleKeys.order(ByteOrder.nativeOrder());
         m_scaleKeys.order(ByteOrder.nativeOrder());
     }
     }
     
     
@@ -141,7 +140,7 @@ public final class AiNodeAnim {
      * Returns the buffer with position keys of this animation channel.<p>
      * Returns the buffer with position keys of this animation channel.<p>
      * 
      * 
      * Position keys consist of a time value (double) and a position (3D vector
      * Position keys consist of a time value (double) and a position (3D vector
-     * of floats), resulting in a total of 24 bytes per entry with padding. 
+     * of floats), resulting in a total of 20 bytes per entry. 
      * The buffer contains {@link #getNumPosKeys()} of these entries.<p>
      * The buffer contains {@link #getNumPosKeys()} of these entries.<p>
      *
      *
      * If there are position keys, there will also be at least one
      * If there are position keys, there will also be at least one
@@ -340,7 +339,7 @@ public final class AiNodeAnim {
      * Returns the buffer with scaling keys of this animation channel.<p>
      * Returns the buffer with scaling keys of this animation channel.<p>
      * 
      * 
      * Scaling keys consist of a time value (double) and a 3D vector of floats,
      * Scaling keys consist of a time value (double) and a 3D vector of floats,
-     * resulting in a total of 24 bytes per entry with padding. The buffer 
+     * resulting in a total of 20 bytes per entry. The buffer 
      * contains {@link #getNumScaleKeys()} of these entries.<p>
      * contains {@link #getNumScaleKeys()} of these entries.<p>
      * 
      * 
      * If there are scaling keys, there will also be at least one
      * If there are scaling keys, there will also be at least one

+ 59 - 1
port/jassimp/jassimp/src/jassimp/Jassimp.java

@@ -96,6 +96,48 @@ public final class Jassimp {
     }
     }
     
     
     
     
+    /**
+     * Returns the size of a struct or ptimitive.<p>
+     * 
+     * @return the result of sizeof call
+     */
+    public static native int getVKeysize();
+
+    /**
+     * @see #getVKeysize
+     */
+    public static native int getQKeysize();
+
+    /**
+     * @see #getVKeysize
+     */
+    public static native int getV3Dsize();
+
+    /**
+     * @see #getVKeysize
+     */
+    public static native int getfloatsize();
+
+    /**
+     * @see #getVKeysize
+     */
+    public static native int getintsize();
+
+    /**
+     * @see #getVKeysize
+     */
+    public static native int getuintsize();
+
+    /**
+     * @see #getVKeysize
+     */
+    public static native int getdoublesize();
+
+    /**
+     * @see #getVKeysize
+     */
+    public static native int getlongsize();
+
     /**
     /**
      * Returns a human readable error description.<p>
      * Returns a human readable error description.<p>
      * 
      * 
@@ -249,8 +291,24 @@ public final class Jassimp {
         /* nothing to do */
         /* nothing to do */
     }
     }
     
     
-    
+    public static final int NATIVE_AIVEKTORKEY_SIZE; 
+    public static final int NATIVE_AIQUATKEY_SIZE; 
+    public static final int NATIVE_AIVEKTOR3D_SIZE; 
+    public static final int NATIVE_FLOAT_SIZE; 
+    public static final int NATIVE_INT_SIZE; 
+    public static final int NATIVE_UINT_SIZE; 
+    public static final int NATIVE_DOUBLE_SIZE; 
+    public static final int NATIVE_LONG_SIZE; 
+
     static {
     static {
         System.loadLibrary("jassimp");
         System.loadLibrary("jassimp");
+    	NATIVE_AIVEKTORKEY_SIZE = getVKeysize();
+    	NATIVE_AIQUATKEY_SIZE = getQKeysize();
+    	NATIVE_AIVEKTOR3D_SIZE = getV3Dsize();
+    	NATIVE_FLOAT_SIZE = getfloatsize();
+    	NATIVE_INT_SIZE = getintsize();
+    	NATIVE_UINT_SIZE = getuintsize();
+    	NATIVE_DOUBLE_SIZE = getdoublesize();
+    	NATIVE_LONG_SIZE = getlongsize();
     }
     }
 }
 }

+ 3 - 2
scripts/IFCImporter/ExpressReader.py

@@ -44,6 +44,7 @@
 entities and data types contained"""
 entities and data types contained"""
 
 
 import sys, os, re
 import sys, os, re
+from collections import OrderedDict
 
 
 re_match_entity = re.compile(r"""
 re_match_entity = re.compile(r"""
 ENTITY\s+(\w+)\s*                                    # 'ENTITY foo'
 ENTITY\s+(\w+)\s*                                    # 'ENTITY foo'
@@ -68,8 +69,8 @@ re_match_field = re.compile(r"""
 
 
 class Schema:
 class Schema:
     def __init__(self):
     def __init__(self):
-        self.entities = {}
-        self.types = {}
+        self.entities = OrderedDict()
+        self.types = OrderedDict()
 
 
 class Entity:
 class Entity:
     def __init__(self,name,parent,members):
     def __init__(self,name,parent,members):

+ 5 - 4
scripts/IFCImporter/entitylist.txt

@@ -1,16 +1,17 @@
-# ============================================================================== 
+# ==============================================================================
 # List of IFC structures needed by Assimp
 # List of IFC structures needed by Assimp
-# ============================================================================== 
+# ==============================================================================
 # use genentitylist.sh to update this list
 # use genentitylist.sh to update this list
 
 
-# This machine-generated list is not complete, it lacks many intermediate 
+# This machine-generated list is not complete, it lacks many intermediate
 # classes in the inheritance hierarchy. Those are magically augmented by the
 # classes in the inheritance hierarchy. Those are magically augmented by the
-# code generator. Also, the names of all used entities need to be present 
+# code generator. Also, the names of all used entities need to be present
 # in the source code for this to work.
 # in the source code for this to work.
 
 
 IfcAnnotation
 IfcAnnotation
 IfcArbitraryClosedProfileDef
 IfcArbitraryClosedProfileDef
 IfcArbitraryOpenProfileDef
 IfcArbitraryOpenProfileDef
+IfcArbitraryProfileDefWithVoids
 IfcAxis1Placement
 IfcAxis1Placement
 IfcAxis2Placement
 IfcAxis2Placement
 IfcAxis2Placement2D
 IfcAxis2Placement2D

+ 9571 - 0
scripts/IFCImporter/schema.exp

@@ -0,0 +1,9571 @@
+(*
+Copyright by:
+International Alliance for Interoperability, 1996-2005
+
+All rights reserved. No part of this documentation may be
+reproduced, stored in a retrieval system, or transmitted
+in any form or by any means, without the prior written
+permission of the owner.
+
+Contents:
+full IFC object model EXPRESS definitions for the IFC2x Edition 3 final version
+
+
+- express longform distribution
+- compiled for EXPRESS version 1 technical corrigendum 2
+
+Issue date:
+December 15, 2005
+
+Development Team:
+Modeling Support Group of the 
+International Alliance for Interoperability
+compiled by Thomas Liebich [email protected]
+*)
+SCHEMA IFC2X3;
+
+TYPE IfcAbsorbedDoseMeasure = REAL;
+END_TYPE;
+
+TYPE IfcAccelerationMeasure = REAL;
+END_TYPE;
+
+TYPE IfcAmountOfSubstanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcAngularVelocityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcAreaMeasure = REAL;
+END_TYPE;
+
+TYPE IfcBoolean = BOOLEAN;
+END_TYPE;
+
+TYPE IfcBoxAlignment = IfcLabel;
+ WHERE
+	WR1 : SELF IN ['top-left', 'top-middle', 'top-right', 'middle-left', 'center', 'middle-right', 'bottom-left', 'bottom-middle', 'bottom-right'];
+END_TYPE;
+
+TYPE IfcComplexNumber = ARRAY [1:2] OF REAL;
+END_TYPE;
+
+TYPE IfcCompoundPlaneAngleMeasure = LIST [3:3] OF INTEGER;
+ WHERE
+	WR1 : { -360 <= SELF[1] < 360 };
+	WR2 : { -60 <= SELF[2] < 60 };
+	WR3 : { -60 <= SELF[3] < 60 };
+	WR4 : ((SELF[1] >= 0) AND (SELF[2] >= 0) AND (SELF[3] >= 0)) OR ((SELF[1] <= 0) AND (SELF[2] <= 0) AND (SELF[3] <= 0));
+END_TYPE;
+
+TYPE IfcContextDependentMeasure = REAL;
+END_TYPE;
+
+TYPE IfcCountMeasure = NUMBER;
+END_TYPE;
+
+TYPE IfcCurvatureMeasure = REAL;
+END_TYPE;
+
+TYPE IfcDayInMonthNumber = INTEGER;
+END_TYPE;
+
+TYPE IfcDaylightSavingHour = INTEGER;
+ WHERE
+	WR1 : { 0 <= SELF <= 2 };
+END_TYPE;
+
+TYPE IfcDescriptiveMeasure = STRING;
+END_TYPE;
+
+TYPE IfcDimensionCount = INTEGER;
+ WHERE
+	WR1 : { 0 < SELF <= 3 };
+END_TYPE;
+
+TYPE IfcDoseEquivalentMeasure = REAL;
+END_TYPE;
+
+TYPE IfcDynamicViscosityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcElectricCapacitanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcElectricChargeMeasure = REAL;
+END_TYPE;
+
+TYPE IfcElectricConductanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcElectricCurrentMeasure = REAL;
+END_TYPE;
+
+TYPE IfcElectricResistanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcElectricVoltageMeasure = REAL;
+END_TYPE;
+
+TYPE IfcEnergyMeasure = REAL;
+END_TYPE;
+
+TYPE IfcFontStyle = STRING;
+ WHERE
+	WR1 : SELF IN ['normal','italic','oblique'];
+END_TYPE;
+
+TYPE IfcFontVariant = STRING;
+ WHERE
+	WR1 : SELF IN ['normal','small-caps'];
+END_TYPE;
+
+TYPE IfcFontWeight = STRING;
+ WHERE
+	WR1 : SELF IN ['normal','small-caps','100','200','300','400','500','600','700','800','900'];
+END_TYPE;
+
+TYPE IfcForceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcFrequencyMeasure = REAL;
+END_TYPE;
+
+TYPE IfcGloballyUniqueId = STRING(22) FIXED;
+END_TYPE;
+
+TYPE IfcHeatFluxDensityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcHeatingValueMeasure = REAL;
+ WHERE
+	WR1 : SELF > 0.;
+END_TYPE;
+
+TYPE IfcHourInDay = INTEGER;
+ WHERE
+	WR1 : { 0 <= SELF < 24 };
+END_TYPE;
+
+TYPE IfcIdentifier = STRING;
+END_TYPE;
+
+TYPE IfcIlluminanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcInductanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcInteger = INTEGER;
+END_TYPE;
+
+TYPE IfcIntegerCountRateMeasure = INTEGER;
+END_TYPE;
+
+TYPE IfcIonConcentrationMeasure = REAL;
+END_TYPE;
+
+TYPE IfcIsothermalMoistureCapacityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcKinematicViscosityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLabel = STRING;
+END_TYPE;
+
+TYPE IfcLengthMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLinearForceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLinearMomentMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLinearStiffnessMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLinearVelocityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLogical = LOGICAL;
+END_TYPE;
+
+TYPE IfcLuminousFluxMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLuminousIntensityDistributionMeasure = REAL;
+END_TYPE;
+
+TYPE IfcLuminousIntensityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMagneticFluxDensityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMagneticFluxMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMassDensityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMassFlowRateMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMassMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMassPerLengthMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMinuteInHour = INTEGER;
+ WHERE
+	WR1 : {0 <= SELF <= 59 };
+END_TYPE;
+
+TYPE IfcModulusOfElasticityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcModulusOfLinearSubgradeReactionMeasure = REAL;
+END_TYPE;
+
+TYPE IfcModulusOfRotationalSubgradeReactionMeasure = REAL;
+END_TYPE;
+
+TYPE IfcModulusOfSubgradeReactionMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMoistureDiffusivityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMolecularWeightMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMomentOfInertiaMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMonetaryMeasure = REAL;
+END_TYPE;
+
+TYPE IfcMonthInYearNumber = INTEGER;
+ WHERE
+	WR1 : { 1<= SELF <= 12 };
+END_TYPE;
+
+TYPE IfcNormalisedRatioMeasure = IfcRatioMeasure;
+ WHERE
+	WR1 : {0.0 <= SELF <= 1.0};
+END_TYPE;
+
+TYPE IfcNumericMeasure = NUMBER;
+END_TYPE;
+
+TYPE IfcPHMeasure = REAL;
+ WHERE
+	WR21 : {0.0 <= SELF <= 14.0};
+END_TYPE;
+
+TYPE IfcParameterValue = REAL;
+END_TYPE;
+
+TYPE IfcPlanarForceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcPlaneAngleMeasure = REAL;
+END_TYPE;
+
+TYPE IfcPositiveLengthMeasure = IfcLengthMeasure;
+ WHERE
+	WR1 : SELF > 0.;
+END_TYPE;
+
+TYPE IfcPositivePlaneAngleMeasure = IfcPlaneAngleMeasure;
+ WHERE
+	WR1 : SELF > 0.;
+END_TYPE;
+
+TYPE IfcPositiveRatioMeasure = IfcRatioMeasure;
+ WHERE
+	WR1 : SELF > 0.;
+END_TYPE;
+
+TYPE IfcPowerMeasure = REAL;
+END_TYPE;
+
+TYPE IfcPresentableText = STRING;
+END_TYPE;
+
+TYPE IfcPressureMeasure = REAL;
+END_TYPE;
+
+TYPE IfcRadioActivityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcRatioMeasure = REAL;
+END_TYPE;
+
+TYPE IfcReal = REAL;
+END_TYPE;
+
+TYPE IfcRotationalFrequencyMeasure = REAL;
+END_TYPE;
+
+TYPE IfcRotationalMassMeasure = REAL;
+END_TYPE;
+
+TYPE IfcRotationalStiffnessMeasure = REAL;
+END_TYPE;
+
+TYPE IfcSecondInMinute = REAL;
+ WHERE
+	WR1 : { 0. <= SELF < 60. };
+END_TYPE;
+
+TYPE IfcSectionModulusMeasure = REAL;
+END_TYPE;
+
+TYPE IfcSectionalAreaIntegralMeasure = REAL;
+END_TYPE;
+
+TYPE IfcShearModulusMeasure = REAL;
+END_TYPE;
+
+TYPE IfcSolidAngleMeasure = REAL;
+END_TYPE;
+
+TYPE IfcSoundPowerMeasure = REAL;
+END_TYPE;
+
+TYPE IfcSoundPressureMeasure = REAL;
+END_TYPE;
+
+TYPE IfcSpecificHeatCapacityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcSpecularExponent = REAL;
+END_TYPE;
+
+TYPE IfcSpecularRoughness = REAL;
+ WHERE
+	WR1 : {0.0 <= SELF <= 1.0};
+END_TYPE;
+
+TYPE IfcTemperatureGradientMeasure = REAL;
+END_TYPE;
+
+TYPE IfcText = STRING;
+END_TYPE;
+
+TYPE IfcTextAlignment = STRING;
+ WHERE
+	WR1 : SELF IN ['left', 'right', 'center', 'justify'];
+END_TYPE;
+
+TYPE IfcTextDecoration = STRING;
+ WHERE
+	WR1 : SELF IN ['none', 'underline', 'overline', 'line-through', 'blink'];
+END_TYPE;
+
+TYPE IfcTextFontName = STRING;
+END_TYPE;
+
+TYPE IfcTextTransformation = STRING;
+ WHERE
+	WR1 : SELF IN ['capitalize', 'uppercase', 'lowercase', 'none'];
+END_TYPE;
+
+TYPE IfcThermalAdmittanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcThermalConductivityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcThermalExpansionCoefficientMeasure = REAL;
+END_TYPE;
+
+TYPE IfcThermalResistanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcThermalTransmittanceMeasure = REAL;
+END_TYPE;
+
+TYPE IfcThermodynamicTemperatureMeasure = REAL;
+END_TYPE;
+
+TYPE IfcTimeMeasure = REAL;
+END_TYPE;
+
+TYPE IfcTimeStamp = INTEGER;
+END_TYPE;
+
+TYPE IfcTorqueMeasure = REAL;
+END_TYPE;
+
+TYPE IfcVaporPermeabilityMeasure = REAL;
+END_TYPE;
+
+TYPE IfcVolumeMeasure = REAL;
+END_TYPE;
+
+TYPE IfcVolumetricFlowRateMeasure = REAL;
+END_TYPE;
+
+TYPE IfcWarpingConstantMeasure = REAL;
+END_TYPE;
+
+TYPE IfcWarpingMomentMeasure = REAL;
+END_TYPE;
+
+TYPE IfcYearNumber = INTEGER;
+END_TYPE;
+
+TYPE IfcActionSourceTypeEnum = ENUMERATION OF
+	(DEAD_LOAD_G
+	,COMPLETION_G1
+	,LIVE_LOAD_Q
+	,SNOW_S
+	,WIND_W
+	,PRESTRESSING_P
+	,SETTLEMENT_U
+	,TEMPERATURE_T
+	,EARTHQUAKE_E
+	,FIRE
+	,IMPULSE
+	,IMPACT
+	,TRANSPORT
+	,ERECTION
+	,PROPPING
+	,SYSTEM_IMPERFECTION
+	,SHRINKAGE
+	,CREEP
+	,LACK_OF_FIT
+	,BUOYANCY
+	,ICE
+	,CURRENT
+	,WAVE
+	,RAIN
+	,BRAKES
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcActionTypeEnum = ENUMERATION OF
+	(PERMANENT_G
+	,VARIABLE_Q
+	,EXTRAORDINARY_A
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcActuatorTypeEnum = ENUMERATION OF
+	(ELECTRICACTUATOR
+	,HANDOPERATEDACTUATOR
+	,HYDRAULICACTUATOR
+	,PNEUMATICACTUATOR
+	,THERMOSTATICACTUATOR
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcAddressTypeEnum = ENUMERATION OF
+	(OFFICE
+	,SITE
+	,HOME
+	,DISTRIBUTIONPOINT
+	,USERDEFINED);
+END_TYPE;
+
+TYPE IfcAheadOrBehind = ENUMERATION OF
+	(AHEAD
+	,BEHIND);
+END_TYPE;
+
+TYPE IfcAirTerminalBoxTypeEnum = ENUMERATION OF
+	(CONSTANTFLOW
+	,VARIABLEFLOWPRESSUREDEPENDANT
+	,VARIABLEFLOWPRESSUREINDEPENDANT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcAirTerminalTypeEnum = ENUMERATION OF
+	(GRILLE
+	,REGISTER
+	,DIFFUSER
+	,EYEBALL
+	,IRIS
+	,LINEARGRILLE
+	,LINEARDIFFUSER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcAirToAirHeatRecoveryTypeEnum = ENUMERATION OF
+	(FIXEDPLATECOUNTERFLOWEXCHANGER
+	,FIXEDPLATECROSSFLOWEXCHANGER
+	,FIXEDPLATEPARALLELFLOWEXCHANGER
+	,ROTARYWHEEL
+	,RUNAROUNDCOILLOOP
+	,HEATPIPE
+	,TWINTOWERENTHALPYRECOVERYLOOPS
+	,THERMOSIPHONSEALEDTUBEHEATEXCHANGERS
+	,THERMOSIPHONCOILTYPEHEATEXCHANGERS
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcAlarmTypeEnum = ENUMERATION OF
+	(BELL
+	,BREAKGLASSBUTTON
+	,LIGHT
+	,MANUALPULLBOX
+	,SIREN
+	,WHISTLE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcAnalysisModelTypeEnum = ENUMERATION OF
+	(IN_PLANE_LOADING_2D
+	,OUT_PLANE_LOADING_2D
+	,LOADING_3D
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcAnalysisTheoryTypeEnum = ENUMERATION OF
+	(FIRST_ORDER_THEORY
+	,SECOND_ORDER_THEORY
+	,THIRD_ORDER_THEORY
+	,FULL_NONLINEAR_THEORY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcArithmeticOperatorEnum = ENUMERATION OF
+	(ADD
+	,DIVIDE
+	,MULTIPLY
+	,SUBTRACT);
+END_TYPE;
+
+TYPE IfcAssemblyPlaceEnum = ENUMERATION OF
+	(SITE
+	,FACTORY
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcBSplineCurveForm = ENUMERATION OF
+	(POLYLINE_FORM
+	,CIRCULAR_ARC
+	,ELLIPTIC_ARC
+	,PARABOLIC_ARC
+	,HYPERBOLIC_ARC
+	,UNSPECIFIED);
+END_TYPE;
+
+TYPE IfcBeamTypeEnum = ENUMERATION OF
+	(BEAM
+	,JOIST
+	,LINTEL
+	,T_BEAM
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcBenchmarkEnum = ENUMERATION OF
+	(GREATERTHAN
+	,GREATERTHANOREQUALTO
+	,LESSTHAN
+	,LESSTHANOREQUALTO
+	,EQUALTO
+	,NOTEQUALTO);
+END_TYPE;
+
+TYPE IfcBoilerTypeEnum = ENUMERATION OF
+	(WATER
+	,STEAM
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcBooleanOperator = ENUMERATION OF
+	(UNION
+	,INTERSECTION
+	,DIFFERENCE);
+END_TYPE;
+
+TYPE IfcBuildingElementProxyTypeEnum = ENUMERATION OF
+	(USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCableCarrierFittingTypeEnum = ENUMERATION OF
+	(BEND
+	,CROSS
+	,REDUCER
+	,TEE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCableCarrierSegmentTypeEnum = ENUMERATION OF
+	(CABLELADDERSEGMENT
+	,CABLETRAYSEGMENT
+	,CABLETRUNKINGSEGMENT
+	,CONDUITSEGMENT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCableSegmentTypeEnum = ENUMERATION OF
+	(CABLESEGMENT
+	,CONDUCTORSEGMENT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcChangeActionEnum = ENUMERATION OF
+	(NOCHANGE
+	,MODIFIED
+	,ADDED
+	,DELETED
+	,MODIFIEDADDED
+	,MODIFIEDDELETED);
+END_TYPE;
+
+TYPE IfcChillerTypeEnum = ENUMERATION OF
+	(AIRCOOLED
+	,WATERCOOLED
+	,HEATRECOVERY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCoilTypeEnum = ENUMERATION OF
+	(DXCOOLINGCOIL
+	,WATERCOOLINGCOIL
+	,STEAMHEATINGCOIL
+	,WATERHEATINGCOIL
+	,ELECTRICHEATINGCOIL
+	,GASHEATINGCOIL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcColumnTypeEnum = ENUMERATION OF
+	(COLUMN
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCompressorTypeEnum = ENUMERATION OF
+	(DYNAMIC
+	,RECIPROCATING
+	,ROTARY
+	,SCROLL
+	,TROCHOIDAL
+	,SINGLESTAGE
+	,BOOSTER
+	,OPENTYPE
+	,HERMETIC
+	,SEMIHERMETIC
+	,WELDEDSHELLHERMETIC
+	,ROLLINGPISTON
+	,ROTARYVANE
+	,SINGLESCREW
+	,TWINSCREW
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCondenserTypeEnum = ENUMERATION OF
+	(WATERCOOLEDSHELLTUBE
+	,WATERCOOLEDSHELLCOIL
+	,WATERCOOLEDTUBEINTUBE
+	,WATERCOOLEDBRAZEDPLATE
+	,AIRCOOLED
+	,EVAPORATIVECOOLED
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcConnectionTypeEnum = ENUMERATION OF
+	(ATPATH
+	,ATSTART
+	,ATEND
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcConstraintEnum = ENUMERATION OF
+	(HARD
+	,SOFT
+	,ADVISORY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcControllerTypeEnum = ENUMERATION OF
+	(FLOATING
+	,PROPORTIONAL
+	,PROPORTIONALINTEGRAL
+	,PROPORTIONALINTEGRALDERIVATIVE
+	,TIMEDTWOPOSITION
+	,TWOPOSITION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCooledBeamTypeEnum = ENUMERATION OF
+	(ACTIVE
+	,PASSIVE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCoolingTowerTypeEnum = ENUMERATION OF
+	(NATURALDRAFT
+	,MECHANICALINDUCEDDRAFT
+	,MECHANICALFORCEDDRAFT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCostScheduleTypeEnum = ENUMERATION OF
+	(BUDGET
+	,COSTPLAN
+	,ESTIMATE
+	,TENDER
+	,PRICEDBILLOFQUANTITIES
+	,UNPRICEDBILLOFQUANTITIES
+	,SCHEDULEOFRATES
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCoveringTypeEnum = ENUMERATION OF
+	(CEILING
+	,FLOORING
+	,CLADDING
+	,ROOFING
+	,INSULATION
+	,MEMBRANE
+	,SLEEVING
+	,WRAPPING
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcCurrencyEnum = ENUMERATION OF
+	(AED
+	,AES
+	,ATS
+	,AUD
+	,BBD
+	,BEG
+	,BGL
+	,BHD
+	,BMD
+	,BND
+	,BRL
+	,BSD
+	,BWP
+	,BZD
+	,CAD
+	,CBD
+	,CHF
+	,CLP
+	,CNY
+	,CYS
+	,CZK
+	,DDP
+	,DEM
+	,DKK
+	,EGL
+	,EST
+	,EUR
+	,FAK
+	,FIM
+	,FJD
+	,FKP
+	,FRF
+	,GBP
+	,GIP
+	,GMD
+	,GRX
+	,HKD
+	,HUF
+	,ICK
+	,IDR
+	,ILS
+	,INR
+	,IRP
+	,ITL
+	,JMD
+	,JOD
+	,JPY
+	,KES
+	,KRW
+	,KWD
+	,KYD
+	,LKR
+	,LUF
+	,MTL
+	,MUR
+	,MXN
+	,MYR
+	,NLG
+	,NZD
+	,OMR
+	,PGK
+	,PHP
+	,PKR
+	,PLN
+	,PTN
+	,QAR
+	,RUR
+	,SAR
+	,SCR
+	,SEK
+	,SGD
+	,SKP
+	,THB
+	,TRL
+	,TTD
+	,TWD
+	,USD
+	,VEB
+	,VND
+	,XEU
+	,ZAR
+	,ZWD
+	,NOK);
+END_TYPE;
+
+TYPE IfcCurtainWallTypeEnum = ENUMERATION OF
+	(USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDamperTypeEnum = ENUMERATION OF
+	(CONTROLDAMPER
+	,FIREDAMPER
+	,SMOKEDAMPER
+	,FIRESMOKEDAMPER
+	,BACKDRAFTDAMPER
+	,RELIEFDAMPER
+	,BLASTDAMPER
+	,GRAVITYDAMPER
+	,GRAVITYRELIEFDAMPER
+	,BALANCINGDAMPER
+	,FUMEHOODEXHAUST
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDataOriginEnum = ENUMERATION OF
+	(MEASURED
+	,PREDICTED
+	,SIMULATED
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDerivedUnitEnum = ENUMERATION OF
+	(ANGULARVELOCITYUNIT
+	,COMPOUNDPLANEANGLEUNIT
+	,DYNAMICVISCOSITYUNIT
+	,HEATFLUXDENSITYUNIT
+	,INTEGERCOUNTRATEUNIT
+	,ISOTHERMALMOISTURECAPACITYUNIT
+	,KINEMATICVISCOSITYUNIT
+	,LINEARVELOCITYUNIT
+	,MASSDENSITYUNIT
+	,MASSFLOWRATEUNIT
+	,MOISTUREDIFFUSIVITYUNIT
+	,MOLECULARWEIGHTUNIT
+	,SPECIFICHEATCAPACITYUNIT
+	,THERMALADMITTANCEUNIT
+	,THERMALCONDUCTANCEUNIT
+	,THERMALRESISTANCEUNIT
+	,THERMALTRANSMITTANCEUNIT
+	,VAPORPERMEABILITYUNIT
+	,VOLUMETRICFLOWRATEUNIT
+	,ROTATIONALFREQUENCYUNIT
+	,TORQUEUNIT
+	,MOMENTOFINERTIAUNIT
+	,LINEARMOMENTUNIT
+	,LINEARFORCEUNIT
+	,PLANARFORCEUNIT
+	,MODULUSOFELASTICITYUNIT
+	,SHEARMODULUSUNIT
+	,LINEARSTIFFNESSUNIT
+	,ROTATIONALSTIFFNESSUNIT
+	,MODULUSOFSUBGRADEREACTIONUNIT
+	,ACCELERATIONUNIT
+	,CURVATUREUNIT
+	,HEATINGVALUEUNIT
+	,IONCONCENTRATIONUNIT
+	,LUMINOUSINTENSITYDISTRIBUTIONUNIT
+	,MASSPERLENGTHUNIT
+	,MODULUSOFLINEARSUBGRADEREACTIONUNIT
+	,MODULUSOFROTATIONALSUBGRADEREACTIONUNIT
+	,PHUNIT
+	,ROTATIONALMASSUNIT
+	,SECTIONAREAINTEGRALUNIT
+	,SECTIONMODULUSUNIT
+	,SOUNDPOWERUNIT
+	,SOUNDPRESSUREUNIT
+	,TEMPERATUREGRADIENTUNIT
+	,THERMALEXPANSIONCOEFFICIENTUNIT
+	,WARPINGCONSTANTUNIT
+	,WARPINGMOMENTUNIT
+	,USERDEFINED);
+END_TYPE;
+
+TYPE IfcDimensionExtentUsage = ENUMERATION OF
+	(ORIGIN
+	,TARGET);
+END_TYPE;
+
+TYPE IfcDirectionSenseEnum = ENUMERATION OF
+	(POSITIVE
+	,NEGATIVE);
+END_TYPE;
+
+TYPE IfcDistributionChamberElementTypeEnum = ENUMERATION OF
+	(FORMEDDUCT
+	,INSPECTIONCHAMBER
+	,INSPECTIONPIT
+	,MANHOLE
+	,METERCHAMBER
+	,SUMP
+	,TRENCH
+	,VALVECHAMBER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDocumentConfidentialityEnum = ENUMERATION OF
+	(PUBLIC
+	,RESTRICTED
+	,CONFIDENTIAL
+	,PERSONAL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDocumentStatusEnum = ENUMERATION OF
+	(DRAFT
+	,FINALDRAFT
+	,FINAL
+	,REVISION
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDoorPanelOperationEnum = ENUMERATION OF
+	(SWINGING
+	,DOUBLE_ACTING
+	,SLIDING
+	,FOLDING
+	,REVOLVING
+	,ROLLINGUP
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDoorPanelPositionEnum = ENUMERATION OF
+	(LEFT
+	,MIDDLE
+	,RIGHT
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDoorStyleConstructionEnum = ENUMERATION OF
+	(ALUMINIUM
+	,HIGH_GRADE_STEEL
+	,STEEL
+	,WOOD
+	,ALUMINIUM_WOOD
+	,ALUMINIUM_PLASTIC
+	,PLASTIC
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDoorStyleOperationEnum = ENUMERATION OF
+	(SINGLE_SWING_LEFT
+	,SINGLE_SWING_RIGHT
+	,DOUBLE_DOOR_SINGLE_SWING
+	,DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_LEFT
+	,DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_RIGHT
+	,DOUBLE_SWING_LEFT
+	,DOUBLE_SWING_RIGHT
+	,DOUBLE_DOOR_DOUBLE_SWING
+	,SLIDING_TO_LEFT
+	,SLIDING_TO_RIGHT
+	,DOUBLE_DOOR_SLIDING
+	,FOLDING_TO_LEFT
+	,FOLDING_TO_RIGHT
+	,DOUBLE_DOOR_FOLDING
+	,REVOLVING
+	,ROLLINGUP
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDuctFittingTypeEnum = ENUMERATION OF
+	(BEND
+	,CONNECTOR
+	,ENTRY
+	,EXIT
+	,JUNCTION
+	,OBSTRUCTION
+	,TRANSITION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDuctSegmentTypeEnum = ENUMERATION OF
+	(RIGIDSEGMENT
+	,FLEXIBLESEGMENT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcDuctSilencerTypeEnum = ENUMERATION OF
+	(FLATOVAL
+	,RECTANGULAR
+	,ROUND
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricApplianceTypeEnum = ENUMERATION OF
+	(COMPUTER
+	,DIRECTWATERHEATER
+	,DISHWASHER
+	,ELECTRICCOOKER
+	,ELECTRICHEATER
+	,FACSIMILE
+	,FREESTANDINGFAN
+	,FREEZER
+	,FRIDGE_FREEZER
+	,HANDDRYER
+	,INDIRECTWATERHEATER
+	,MICROWAVE
+	,PHOTOCOPIER
+	,PRINTER
+	,REFRIGERATOR
+	,RADIANTHEATER
+	,SCANNER
+	,TELEPHONE
+	,TUMBLEDRYER
+	,TV
+	,VENDINGMACHINE
+	,WASHINGMACHINE
+	,WATERHEATER
+	,WATERCOOLER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricCurrentEnum = ENUMERATION OF
+	(ALTERNATING
+	,DIRECT
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricDistributionPointFunctionEnum = ENUMERATION OF
+	(ALARMPANEL
+	,CONSUMERUNIT
+	,CONTROLPANEL
+	,DISTRIBUTIONBOARD
+	,GASDETECTORPANEL
+	,INDICATORPANEL
+	,MIMICPANEL
+	,MOTORCONTROLCENTRE
+	,SWITCHBOARD
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricFlowStorageDeviceTypeEnum = ENUMERATION OF
+	(BATTERY
+	,CAPACITORBANK
+	,HARMONICFILTER
+	,INDUCTORBANK
+	,UPS
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricGeneratorTypeEnum = ENUMERATION OF
+	(USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricHeaterTypeEnum = ENUMERATION OF
+	(ELECTRICPOINTHEATER
+	,ELECTRICCABLEHEATER
+	,ELECTRICMATHEATER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricMotorTypeEnum = ENUMERATION OF
+	(DC
+	,INDUCTION
+	,POLYPHASE
+	,RELUCTANCESYNCHRONOUS
+	,SYNCHRONOUS
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElectricTimeControlTypeEnum = ENUMERATION OF
+	(TIMECLOCK
+	,TIMEDELAY
+	,RELAY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElementAssemblyTypeEnum = ENUMERATION OF
+	(ACCESSORY_ASSEMBLY
+	,ARCH
+	,BEAM_GRID
+	,BRACED_FRAME
+	,GIRDER
+	,REINFORCEMENT_UNIT
+	,RIGID_FRAME
+	,SLAB_FIELD
+	,TRUSS
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcElementCompositionEnum = ENUMERATION OF
+	(COMPLEX
+	,ELEMENT
+	,PARTIAL);
+END_TYPE;
+
+TYPE IfcEnergySequenceEnum = ENUMERATION OF
+	(PRIMARY
+	,SECONDARY
+	,TERTIARY
+	,AUXILIARY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcEnvironmentalImpactCategoryEnum = ENUMERATION OF
+	(COMBINEDVALUE
+	,DISPOSAL
+	,EXTRACTION
+	,INSTALLATION
+	,MANUFACTURE
+	,TRANSPORTATION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcEvaporativeCoolerTypeEnum = ENUMERATION OF
+	(DIRECTEVAPORATIVERANDOMMEDIAAIRCOOLER
+	,DIRECTEVAPORATIVERIGIDMEDIAAIRCOOLER
+	,DIRECTEVAPORATIVESLINGERSPACKAGEDAIRCOOLER
+	,DIRECTEVAPORATIVEPACKAGEDROTARYAIRCOOLER
+	,DIRECTEVAPORATIVEAIRWASHER
+	,INDIRECTEVAPORATIVEPACKAGEAIRCOOLER
+	,INDIRECTEVAPORATIVEWETCOIL
+	,INDIRECTEVAPORATIVECOOLINGTOWERORCOILCOOLER
+	,INDIRECTDIRECTCOMBINATION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcEvaporatorTypeEnum = ENUMERATION OF
+	(DIRECTEXPANSIONSHELLANDTUBE
+	,DIRECTEXPANSIONTUBEINTUBE
+	,DIRECTEXPANSIONBRAZEDPLATE
+	,FLOODEDSHELLANDTUBE
+	,SHELLANDCOIL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcFanTypeEnum = ENUMERATION OF
+	(CENTRIFUGALFORWARDCURVED
+	,CENTRIFUGALRADIAL
+	,CENTRIFUGALBACKWARDINCLINEDCURVED
+	,CENTRIFUGALAIRFOIL
+	,TUBEAXIAL
+	,VANEAXIAL
+	,PROPELLORAXIAL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcFilterTypeEnum = ENUMERATION OF
+	(AIRPARTICLEFILTER
+	,ODORFILTER
+	,OILFILTER
+	,STRAINER
+	,WATERFILTER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcFireSuppressionTerminalTypeEnum = ENUMERATION OF
+	(BREECHINGINLET
+	,FIREHYDRANT
+	,HOSEREEL
+	,SPRINKLER
+	,SPRINKLERDEFLECTOR
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcFlowDirectionEnum = ENUMERATION OF
+	(SOURCE
+	,SINK
+	,SOURCEANDSINK
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcFlowInstrumentTypeEnum = ENUMERATION OF
+	(PRESSUREGAUGE
+	,THERMOMETER
+	,AMMETER
+	,FREQUENCYMETER
+	,POWERFACTORMETER
+	,PHASEANGLEMETER
+	,VOLTMETER_PEAK
+	,VOLTMETER_RMS
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcFlowMeterTypeEnum = ENUMERATION OF
+	(ELECTRICMETER
+	,ENERGYMETER
+	,FLOWMETER
+	,GASMETER
+	,OILMETER
+	,WATERMETER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcFootingTypeEnum = ENUMERATION OF
+	(FOOTING_BEAM
+	,PAD_FOOTING
+	,PILE_CAP
+	,STRIP_FOOTING
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcGasTerminalTypeEnum = ENUMERATION OF
+	(GASAPPLIANCE
+	,GASBOOSTER
+	,GASBURNER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcGeometricProjectionEnum = ENUMERATION OF
+	(GRAPH_VIEW
+	,SKETCH_VIEW
+	,MODEL_VIEW
+	,PLAN_VIEW
+	,REFLECTED_PLAN_VIEW
+	,SECTION_VIEW
+	,ELEVATION_VIEW
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcGlobalOrLocalEnum = ENUMERATION OF
+	(GLOBAL_COORDS
+	,LOCAL_COORDS);
+END_TYPE;
+
+TYPE IfcHeatExchangerTypeEnum = ENUMERATION OF
+	(PLATE
+	,SHELLANDTUBE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcHumidifierTypeEnum = ENUMERATION OF
+	(STEAMINJECTION
+	,ADIABATICAIRWASHER
+	,ADIABATICPAN
+	,ADIABATICWETTEDELEMENT
+	,ADIABATICATOMIZING
+	,ADIABATICULTRASONIC
+	,ADIABATICRIGIDMEDIA
+	,ADIABATICCOMPRESSEDAIRNOZZLE
+	,ASSISTEDELECTRIC
+	,ASSISTEDNATURALGAS
+	,ASSISTEDPROPANE
+	,ASSISTEDBUTANE
+	,ASSISTEDSTEAM
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcInternalOrExternalEnum = ENUMERATION OF
+	(INTERNAL
+	,EXTERNAL
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcInventoryTypeEnum = ENUMERATION OF
+	(ASSETINVENTORY
+	,SPACEINVENTORY
+	,FURNITUREINVENTORY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcJunctionBoxTypeEnum = ENUMERATION OF
+	(USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcLampTypeEnum = ENUMERATION OF
+	(COMPACTFLUORESCENT
+	,FLUORESCENT
+	,HIGHPRESSUREMERCURY
+	,HIGHPRESSURESODIUM
+	,METALHALIDE
+	,TUNGSTENFILAMENT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcLayerSetDirectionEnum = ENUMERATION OF
+	(AXIS1
+	,AXIS2
+	,AXIS3);
+END_TYPE;
+
+TYPE IfcLightDistributionCurveEnum = ENUMERATION OF
+	(TYPE_A
+	,TYPE_B
+	,TYPE_C
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcLightEmissionSourceEnum = ENUMERATION OF
+	(COMPACTFLUORESCENT
+	,FLUORESCENT
+	,HIGHPRESSUREMERCURY
+	,HIGHPRESSURESODIUM
+	,LIGHTEMITTINGDIODE
+	,LOWPRESSURESODIUM
+	,LOWVOLTAGEHALOGEN
+	,MAINVOLTAGEHALOGEN
+	,METALHALIDE
+	,TUNGSTENFILAMENT
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcLightFixtureTypeEnum = ENUMERATION OF
+	(POINTSOURCE
+	,DIRECTIONSOURCE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcLoadGroupTypeEnum = ENUMERATION OF
+	(LOAD_GROUP
+	,LOAD_CASE
+	,LOAD_COMBINATION_GROUP
+	,LOAD_COMBINATION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcLogicalOperatorEnum = ENUMERATION OF
+	(LOGICALAND
+	,LOGICALOR);
+END_TYPE;
+
+TYPE IfcMemberTypeEnum = ENUMERATION OF
+	(BRACE
+	,CHORD
+	,COLLAR
+	,MEMBER
+	,MULLION
+	,PLATE
+	,POST
+	,PURLIN
+	,RAFTER
+	,STRINGER
+	,STRUT
+	,STUD
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcMotorConnectionTypeEnum = ENUMERATION OF
+	(BELTDRIVE
+	,COUPLING
+	,DIRECTDRIVE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcNullStyle = ENUMERATION OF
+	(NULL);
+END_TYPE;
+
+TYPE IfcObjectTypeEnum = ENUMERATION OF
+	(PRODUCT
+	,PROCESS
+	,CONTROL
+	,RESOURCE
+	,ACTOR
+	,GROUP
+	,PROJECT
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcObjectiveEnum = ENUMERATION OF
+	(CODECOMPLIANCE
+	,DESIGNINTENT
+	,HEALTHANDSAFETY
+	,REQUIREMENT
+	,SPECIFICATION
+	,TRIGGERCONDITION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcOccupantTypeEnum = ENUMERATION OF
+	(ASSIGNEE
+	,ASSIGNOR
+	,LESSEE
+	,LESSOR
+	,LETTINGAGENT
+	,OWNER
+	,TENANT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcOutletTypeEnum = ENUMERATION OF
+	(AUDIOVISUALOUTLET
+	,COMMUNICATIONSOUTLET
+	,POWEROUTLET
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPermeableCoveringOperationEnum = ENUMERATION OF
+	(GRILL
+	,LOUVER
+	,SCREEN
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPhysicalOrVirtualEnum = ENUMERATION OF
+	(PHYSICAL
+	,VIRTUAL
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPileConstructionEnum = ENUMERATION OF
+	(CAST_IN_PLACE
+	,COMPOSITE
+	,PRECAST_CONCRETE
+	,PREFAB_STEEL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPileTypeEnum = ENUMERATION OF
+	(COHESION
+	,FRICTION
+	,SUPPORT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPipeFittingTypeEnum = ENUMERATION OF
+	(BEND
+	,CONNECTOR
+	,ENTRY
+	,EXIT
+	,JUNCTION
+	,OBSTRUCTION
+	,TRANSITION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPipeSegmentTypeEnum = ENUMERATION OF
+	(FLEXIBLESEGMENT
+	,RIGIDSEGMENT
+	,GUTTER
+	,SPOOL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPlateTypeEnum = ENUMERATION OF
+	(CURTAIN_PANEL
+	,SHEET
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcProcedureTypeEnum = ENUMERATION OF
+	(ADVICE_CAUTION
+	,ADVICE_NOTE
+	,ADVICE_WARNING
+	,CALIBRATION
+	,DIAGNOSTIC
+	,SHUTDOWN
+	,STARTUP
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcProfileTypeEnum = ENUMERATION OF
+	(CURVE
+	,AREA);
+END_TYPE;
+
+TYPE IfcProjectOrderRecordTypeEnum = ENUMERATION OF
+	(CHANGE
+	,MAINTENANCE
+	,MOVE
+	,PURCHASE
+	,WORK
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcProjectOrderTypeEnum = ENUMERATION OF
+	(CHANGEORDER
+	,MAINTENANCEWORKORDER
+	,MOVEORDER
+	,PURCHASEORDER
+	,WORKORDER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcProjectedOrTrueLengthEnum = ENUMERATION OF
+	(PROJECTED_LENGTH
+	,TRUE_LENGTH);
+END_TYPE;
+
+TYPE IfcPropertySourceEnum = ENUMERATION OF
+	(DESIGN
+	,DESIGNMAXIMUM
+	,DESIGNMINIMUM
+	,SIMULATED
+	,ASBUILT
+	,COMMISSIONING
+	,MEASURED
+	,USERDEFINED
+	,NOTKNOWN);
+END_TYPE;
+
+TYPE IfcProtectiveDeviceTypeEnum = ENUMERATION OF
+	(FUSEDISCONNECTOR
+	,CIRCUITBREAKER
+	,EARTHFAILUREDEVICE
+	,RESIDUALCURRENTCIRCUITBREAKER
+	,RESIDUALCURRENTSWITCH
+	,VARISTOR
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcPumpTypeEnum = ENUMERATION OF
+	(CIRCULATOR
+	,ENDSUCTION
+	,SPLITCASE
+	,VERTICALINLINE
+	,VERTICALTURBINE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcRailingTypeEnum = ENUMERATION OF
+	(HANDRAIL
+	,GUARDRAIL
+	,BALUSTRADE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcRampFlightTypeEnum = ENUMERATION OF
+	(STRAIGHT
+	,SPIRAL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcRampTypeEnum = ENUMERATION OF
+	(STRAIGHT_RUN_RAMP
+	,TWO_STRAIGHT_RUN_RAMP
+	,QUARTER_TURN_RAMP
+	,TWO_QUARTER_TURN_RAMP
+	,HALF_TURN_RAMP
+	,SPIRAL_RAMP
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcReflectanceMethodEnum = ENUMERATION OF
+	(BLINN
+	,FLAT
+	,GLASS
+	,MATT
+	,METAL
+	,MIRROR
+	,PHONG
+	,PLASTIC
+	,STRAUSS
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcReinforcingBarRoleEnum = ENUMERATION OF
+	(MAIN
+	,SHEAR
+	,LIGATURE
+	,STUD
+	,PUNCHING
+	,EDGE
+	,RING
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcReinforcingBarSurfaceEnum = ENUMERATION OF
+	(PLAIN
+	,TEXTURED);
+END_TYPE;
+
+TYPE IfcResourceConsumptionEnum = ENUMERATION OF
+	(CONSUMED
+	,PARTIALLYCONSUMED
+	,NOTCONSUMED
+	,OCCUPIED
+	,PARTIALLYOCCUPIED
+	,NOTOCCUPIED
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcRibPlateDirectionEnum = ENUMERATION OF
+	(DIRECTION_X
+	,DIRECTION_Y);
+END_TYPE;
+
+TYPE IfcRoleEnum = ENUMERATION OF
+	(SUPPLIER
+	,MANUFACTURER
+	,CONTRACTOR
+	,SUBCONTRACTOR
+	,ARCHITECT
+	,STRUCTURALENGINEER
+	,COSTENGINEER
+	,CLIENT
+	,BUILDINGOWNER
+	,BUILDINGOPERATOR
+	,MECHANICALENGINEER
+	,ELECTRICALENGINEER
+	,PROJECTMANAGER
+	,FACILITIESMANAGER
+	,CIVILENGINEER
+	,COMISSIONINGENGINEER
+	,ENGINEER
+	,OWNER
+	,CONSULTANT
+	,CONSTRUCTIONMANAGER
+	,FIELDCONSTRUCTIONMANAGER
+	,RESELLER
+	,USERDEFINED);
+END_TYPE;
+
+TYPE IfcRoofTypeEnum = ENUMERATION OF
+	(FLAT_ROOF
+	,SHED_ROOF
+	,GABLE_ROOF
+	,HIP_ROOF
+	,HIPPED_GABLE_ROOF
+	,GAMBREL_ROOF
+	,MANSARD_ROOF
+	,BARREL_ROOF
+	,RAINBOW_ROOF
+	,BUTTERFLY_ROOF
+	,PAVILION_ROOF
+	,DOME_ROOF
+	,FREEFORM
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSIPrefix = ENUMERATION OF
+	(EXA
+	,PETA
+	,TERA
+	,GIGA
+	,MEGA
+	,KILO
+	,HECTO
+	,DECA
+	,DECI
+	,CENTI
+	,MILLI
+	,MICRO
+	,NANO
+	,PICO
+	,FEMTO
+	,ATTO);
+END_TYPE;
+
+TYPE IfcSIUnitName = ENUMERATION OF
+	(AMPERE
+	,BECQUEREL
+	,CANDELA
+	,COULOMB
+	,CUBIC_METRE
+	,DEGREE_CELSIUS
+	,FARAD
+	,GRAM
+	,GRAY
+	,HENRY
+	,HERTZ
+	,JOULE
+	,KELVIN
+	,LUMEN
+	,LUX
+	,METRE
+	,MOLE
+	,NEWTON
+	,OHM
+	,PASCAL
+	,RADIAN
+	,SECOND
+	,SIEMENS
+	,SIEVERT
+	,SQUARE_METRE
+	,STERADIAN
+	,TESLA
+	,VOLT
+	,WATT
+	,WEBER);
+END_TYPE;
+
+TYPE IfcSanitaryTerminalTypeEnum = ENUMERATION OF
+	(BATH
+	,BIDET
+	,CISTERN
+	,SHOWER
+	,SINK
+	,SANITARYFOUNTAIN
+	,TOILETPAN
+	,URINAL
+	,WASHHANDBASIN
+	,WCSEAT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSectionTypeEnum = ENUMERATION OF
+	(UNIFORM
+	,TAPERED);
+END_TYPE;
+
+TYPE IfcSensorTypeEnum = ENUMERATION OF
+	(CO2SENSOR
+	,FIRESENSOR
+	,FLOWSENSOR
+	,GASSENSOR
+	,HEATSENSOR
+	,HUMIDITYSENSOR
+	,LIGHTSENSOR
+	,MOISTURESENSOR
+	,MOVEMENTSENSOR
+	,PRESSURESENSOR
+	,SMOKESENSOR
+	,SOUNDSENSOR
+	,TEMPERATURESENSOR
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSequenceEnum = ENUMERATION OF
+	(START_START
+	,START_FINISH
+	,FINISH_START
+	,FINISH_FINISH
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcServiceLifeFactorTypeEnum = ENUMERATION OF
+	(A_QUALITYOFCOMPONENTS
+	,B_DESIGNLEVEL
+	,C_WORKEXECUTIONLEVEL
+	,D_INDOORENVIRONMENT
+	,E_OUTDOORENVIRONMENT
+	,F_INUSECONDITIONS
+	,G_MAINTENANCELEVEL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcServiceLifeTypeEnum = ENUMERATION OF
+	(ACTUALSERVICELIFE
+	,EXPECTEDSERVICELIFE
+	,OPTIMISTICREFERENCESERVICELIFE
+	,PESSIMISTICREFERENCESERVICELIFE
+	,REFERENCESERVICELIFE);
+END_TYPE;
+
+TYPE IfcSlabTypeEnum = ENUMERATION OF
+	(FLOOR
+	,ROOF
+	,LANDING
+	,BASESLAB
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSoundScaleEnum = ENUMERATION OF
+	(DBA
+	,DBB
+	,DBC
+	,NC
+	,NR
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSpaceHeaterTypeEnum = ENUMERATION OF
+	(SECTIONALRADIATOR
+	,PANELRADIATOR
+	,TUBULARRADIATOR
+	,CONVECTOR
+	,BASEBOARDHEATER
+	,FINNEDTUBEUNIT
+	,UNITHEATER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSpaceTypeEnum = ENUMERATION OF
+	(USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcStackTerminalTypeEnum = ENUMERATION OF
+	(BIRDCAGE
+	,COWL
+	,RAINWATERHOPPER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcStairFlightTypeEnum = ENUMERATION OF
+	(STRAIGHT
+	,WINDER
+	,SPIRAL
+	,CURVED
+	,FREEFORM
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcStairTypeEnum = ENUMERATION OF
+	(STRAIGHT_RUN_STAIR
+	,TWO_STRAIGHT_RUN_STAIR
+	,QUARTER_WINDING_STAIR
+	,QUARTER_TURN_STAIR
+	,HALF_WINDING_STAIR
+	,HALF_TURN_STAIR
+	,TWO_QUARTER_WINDING_STAIR
+	,TWO_QUARTER_TURN_STAIR
+	,THREE_QUARTER_WINDING_STAIR
+	,THREE_QUARTER_TURN_STAIR
+	,SPIRAL_STAIR
+	,DOUBLE_RETURN_STAIR
+	,CURVED_RUN_STAIR
+	,TWO_CURVED_RUN_STAIR
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcStateEnum = ENUMERATION OF
+	(READWRITE
+	,READONLY
+	,LOCKED
+	,READWRITELOCKED
+	,READONLYLOCKED);
+END_TYPE;
+
+TYPE IfcStructuralCurveTypeEnum = ENUMERATION OF
+	(RIGID_JOINED_MEMBER
+	,PIN_JOINED_MEMBER
+	,CABLE
+	,TENSION_MEMBER
+	,COMPRESSION_MEMBER
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcStructuralSurfaceTypeEnum = ENUMERATION OF
+	(BENDING_ELEMENT
+	,MEMBRANE_ELEMENT
+	,SHELL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSurfaceSide = ENUMERATION OF
+	(POSITIVE
+	,NEGATIVE
+	,BOTH);
+END_TYPE;
+
+TYPE IfcSurfaceTextureEnum = ENUMERATION OF
+	(BUMP
+	,OPACITY
+	,REFLECTION
+	,SELFILLUMINATION
+	,SHININESS
+	,SPECULAR
+	,TEXTURE
+	,TRANSPARENCYMAP
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcSwitchingDeviceTypeEnum = ENUMERATION OF
+	(CONTACTOR
+	,EMERGENCYSTOP
+	,STARTER
+	,SWITCHDISCONNECTOR
+	,TOGGLESWITCH
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTankTypeEnum = ENUMERATION OF
+	(PREFORMED
+	,SECTIONAL
+	,EXPANSION
+	,PRESSUREVESSEL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTendonTypeEnum = ENUMERATION OF
+	(STRAND
+	,WIRE
+	,BAR
+	,COATED
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTextPath = ENUMERATION OF
+	(LEFT
+	,RIGHT
+	,UP
+	,DOWN);
+END_TYPE;
+
+TYPE IfcThermalLoadSourceEnum = ENUMERATION OF
+	(PEOPLE
+	,LIGHTING
+	,EQUIPMENT
+	,VENTILATIONINDOORAIR
+	,VENTILATIONOUTSIDEAIR
+	,RECIRCULATEDAIR
+	,EXHAUSTAIR
+	,AIREXCHANGERATE
+	,DRYBULBTEMPERATURE
+	,RELATIVEHUMIDITY
+	,INFILTRATION
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcThermalLoadTypeEnum = ENUMERATION OF
+	(SENSIBLE
+	,LATENT
+	,RADIANT
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTimeSeriesDataTypeEnum = ENUMERATION OF
+	(CONTINUOUS
+	,DISCRETE
+	,DISCRETEBINARY
+	,PIECEWISEBINARY
+	,PIECEWISECONSTANT
+	,PIECEWISECONTINUOUS
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTimeSeriesScheduleTypeEnum = ENUMERATION OF
+	(ANNUAL
+	,MONTHLY
+	,WEEKLY
+	,DAILY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTransformerTypeEnum = ENUMERATION OF
+	(CURRENT
+	,FREQUENCY
+	,VOLTAGE
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTransitionCode = ENUMERATION OF
+	(DISCONTINUOUS
+	,CONTINUOUS
+	,CONTSAMEGRADIENT
+	,CONTSAMEGRADIENTSAMECURVATURE);
+END_TYPE;
+
+TYPE IfcTransportElementTypeEnum = ENUMERATION OF
+	(ELEVATOR
+	,ESCALATOR
+	,MOVINGWALKWAY
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcTrimmingPreference = ENUMERATION OF
+	(CARTESIAN
+	,PARAMETER
+	,UNSPECIFIED);
+END_TYPE;
+
+TYPE IfcTubeBundleTypeEnum = ENUMERATION OF
+	(FINNED
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcUnitEnum = ENUMERATION OF
+	(ABSORBEDDOSEUNIT
+	,AMOUNTOFSUBSTANCEUNIT
+	,AREAUNIT
+	,DOSEEQUIVALENTUNIT
+	,ELECTRICCAPACITANCEUNIT
+	,ELECTRICCHARGEUNIT
+	,ELECTRICCONDUCTANCEUNIT
+	,ELECTRICCURRENTUNIT
+	,ELECTRICRESISTANCEUNIT
+	,ELECTRICVOLTAGEUNIT
+	,ENERGYUNIT
+	,FORCEUNIT
+	,FREQUENCYUNIT
+	,ILLUMINANCEUNIT
+	,INDUCTANCEUNIT
+	,LENGTHUNIT
+	,LUMINOUSFLUXUNIT
+	,LUMINOUSINTENSITYUNIT
+	,MAGNETICFLUXDENSITYUNIT
+	,MAGNETICFLUXUNIT
+	,MASSUNIT
+	,PLANEANGLEUNIT
+	,POWERUNIT
+	,PRESSUREUNIT
+	,RADIOACTIVITYUNIT
+	,SOLIDANGLEUNIT
+	,THERMODYNAMICTEMPERATUREUNIT
+	,TIMEUNIT
+	,VOLUMEUNIT
+	,USERDEFINED);
+END_TYPE;
+
+TYPE IfcUnitaryEquipmentTypeEnum = ENUMERATION OF
+	(AIRHANDLER
+	,AIRCONDITIONINGUNIT
+	,SPLITSYSTEM
+	,ROOFTOPUNIT
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcValveTypeEnum = ENUMERATION OF
+	(AIRRELEASE
+	,ANTIVACUUM
+	,CHANGEOVER
+	,CHECK
+	,COMMISSIONING
+	,DIVERTING
+	,DRAWOFFCOCK
+	,DOUBLECHECK
+	,DOUBLEREGULATING
+	,FAUCET
+	,FLUSHING
+	,GASCOCK
+	,GASTAP
+	,ISOLATING
+	,MIXING
+	,PRESSUREREDUCING
+	,PRESSURERELIEF
+	,REGULATING
+	,SAFETYCUTOFF
+	,STEAMTRAP
+	,STOPCOCK
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcVibrationIsolatorTypeEnum = ENUMERATION OF
+	(COMPRESSION
+	,SPRING
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcWallTypeEnum = ENUMERATION OF
+	(STANDARD
+	,POLYGONAL
+	,SHEAR
+	,ELEMENTEDWALL
+	,PLUMBINGWALL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcWasteTerminalTypeEnum = ENUMERATION OF
+	(FLOORTRAP
+	,FLOORWASTE
+	,GULLYSUMP
+	,GULLYTRAP
+	,GREASEINTERCEPTOR
+	,OILINTERCEPTOR
+	,PETROLINTERCEPTOR
+	,ROOFDRAIN
+	,WASTEDISPOSALUNIT
+	,WASTETRAP
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcWindowPanelOperationEnum = ENUMERATION OF
+	(SIDEHUNGRIGHTHAND
+	,SIDEHUNGLEFTHAND
+	,TILTANDTURNRIGHTHAND
+	,TILTANDTURNLEFTHAND
+	,TOPHUNG
+	,BOTTOMHUNG
+	,PIVOTHORIZONTAL
+	,PIVOTVERTICAL
+	,SLIDINGHORIZONTAL
+	,SLIDINGVERTICAL
+	,REMOVABLECASEMENT
+	,FIXEDCASEMENT
+	,OTHEROPERATION
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcWindowPanelPositionEnum = ENUMERATION OF
+	(LEFT
+	,MIDDLE
+	,RIGHT
+	,BOTTOM
+	,TOP
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcWindowStyleConstructionEnum = ENUMERATION OF
+	(ALUMINIUM
+	,HIGH_GRADE_STEEL
+	,STEEL
+	,WOOD
+	,ALUMINIUM_WOOD
+	,PLASTIC
+	,OTHER_CONSTRUCTION
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcWindowStyleOperationEnum = ENUMERATION OF
+	(SINGLE_PANEL
+	,DOUBLE_PANEL_VERTICAL
+	,DOUBLE_PANEL_HORIZONTAL
+	,TRIPLE_PANEL_VERTICAL
+	,TRIPLE_PANEL_BOTTOM
+	,TRIPLE_PANEL_TOP
+	,TRIPLE_PANEL_LEFT
+	,TRIPLE_PANEL_RIGHT
+	,TRIPLE_PANEL_HORIZONTAL
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcWorkControlTypeEnum = ENUMERATION OF
+	(ACTUAL
+	,BASELINE
+	,PLANNED
+	,USERDEFINED
+	,NOTDEFINED);
+END_TYPE;
+
+TYPE IfcActorSelect = SELECT
+	(IfcOrganization
+	,IfcPerson
+	,IfcPersonAndOrganization);
+END_TYPE;
+
+TYPE IfcAppliedValueSelect = SELECT
+	(IfcRatioMeasure
+	,IfcMeasureWithUnit
+	,IfcMonetaryMeasure);
+END_TYPE;
+
+TYPE IfcAxis2Placement = SELECT
+	(IfcAxis2Placement2D
+	,IfcAxis2Placement3D);
+END_TYPE;
+
+TYPE IfcBooleanOperand = SELECT
+	(IfcSolidModel
+	,IfcHalfSpaceSolid
+	,IfcBooleanResult
+	,IfcCsgPrimitive3D);
+END_TYPE;
+
+TYPE IfcCharacterStyleSelect = SELECT
+	(IfcTextStyleForDefinedFont);
+END_TYPE;
+
+TYPE IfcClassificationNotationSelect = SELECT
+	(IfcClassificationNotation
+	,IfcClassificationReference);
+END_TYPE;
+
+TYPE IfcColour = SELECT
+	(IfcColourSpecification
+	,IfcPreDefinedColour);
+END_TYPE;
+
+TYPE IfcColourOrFactor = SELECT
+	(IfcColourRgb
+	,IfcNormalisedRatioMeasure);
+END_TYPE;
+
+TYPE IfcConditionCriterionSelect = SELECT
+	(IfcLabel
+	,IfcMeasureWithUnit);
+END_TYPE;
+
+TYPE IfcCsgSelect = SELECT
+	(IfcBooleanResult
+	,IfcCsgPrimitive3D);
+END_TYPE;
+
+TYPE IfcCurveFontOrScaledCurveFontSelect = SELECT
+	(IfcCurveStyleFontSelect
+	,IfcCurveStyleFontAndScaling);
+END_TYPE;
+
+TYPE IfcCurveOrEdgeCurve = SELECT
+	(IfcBoundedCurve
+	,IfcEdgeCurve);
+END_TYPE;
+
+TYPE IfcCurveStyleFontSelect = SELECT
+	(IfcPreDefinedCurveFont
+	,IfcCurveStyleFont);
+END_TYPE;
+
+TYPE IfcDateTimeSelect = SELECT
+	(IfcCalendarDate
+	,IfcLocalTime
+	,IfcDateAndTime);
+END_TYPE;
+
+TYPE IfcDefinedSymbolSelect = SELECT
+	(IfcPreDefinedSymbol
+	,IfcExternallyDefinedSymbol);
+END_TYPE;
+
+TYPE IfcDerivedMeasureValue = SELECT
+	(IfcVolumetricFlowRateMeasure
+	,IfcTimeStamp
+	,IfcThermalTransmittanceMeasure
+	,IfcThermalResistanceMeasure
+	,IfcThermalAdmittanceMeasure
+	,IfcPressureMeasure
+	,IfcPowerMeasure
+	,IfcMassFlowRateMeasure
+	,IfcMassDensityMeasure
+	,IfcLinearVelocityMeasure
+	,IfcKinematicViscosityMeasure
+	,IfcIntegerCountRateMeasure
+	,IfcHeatFluxDensityMeasure
+	,IfcFrequencyMeasure
+	,IfcEnergyMeasure
+	,IfcElectricVoltageMeasure
+	,IfcDynamicViscosityMeasure
+	,IfcCompoundPlaneAngleMeasure
+	,IfcAngularVelocityMeasure
+	,IfcThermalConductivityMeasure
+	,IfcMolecularWeightMeasure
+	,IfcVaporPermeabilityMeasure
+	,IfcMoistureDiffusivityMeasure
+	,IfcIsothermalMoistureCapacityMeasure
+	,IfcSpecificHeatCapacityMeasure
+	,IfcMonetaryMeasure
+	,IfcMagneticFluxDensityMeasure
+	,IfcMagneticFluxMeasure
+	,IfcLuminousFluxMeasure
+	,IfcForceMeasure
+	,IfcInductanceMeasure
+	,IfcIlluminanceMeasure
+	,IfcElectricResistanceMeasure
+	,IfcElectricConductanceMeasure
+	,IfcElectricChargeMeasure
+	,IfcDoseEquivalentMeasure
+	,IfcElectricCapacitanceMeasure
+	,IfcAbsorbedDoseMeasure
+	,IfcRadioActivityMeasure
+	,IfcRotationalFrequencyMeasure
+	,IfcTorqueMeasure
+	,IfcAccelerationMeasure
+	,IfcLinearForceMeasure
+	,IfcLinearStiffnessMeasure
+	,IfcModulusOfSubgradeReactionMeasure
+	,IfcModulusOfElasticityMeasure
+	,IfcMomentOfInertiaMeasure
+	,IfcPlanarForceMeasure
+	,IfcRotationalStiffnessMeasure
+	,IfcShearModulusMeasure
+	,IfcLinearMomentMeasure
+	,IfcLuminousIntensityDistributionMeasure
+	,IfcCurvatureMeasure
+	,IfcMassPerLengthMeasure
+	,IfcModulusOfLinearSubgradeReactionMeasure
+	,IfcModulusOfRotationalSubgradeReactionMeasure
+	,IfcRotationalMassMeasure
+	,IfcSectionalAreaIntegralMeasure
+	,IfcSectionModulusMeasure
+	,IfcTemperatureGradientMeasure
+	,IfcThermalExpansionCoefficientMeasure
+	,IfcWarpingConstantMeasure
+	,IfcWarpingMomentMeasure
+	,IfcSoundPowerMeasure
+	,IfcSoundPressureMeasure
+	,IfcHeatingValueMeasure
+	,IfcPHMeasure
+	,IfcIonConcentrationMeasure);
+END_TYPE;
+
+TYPE IfcDocumentSelect = SELECT
+	(IfcDocumentReference
+	,IfcDocumentInformation);
+END_TYPE;
+
+TYPE IfcDraughtingCalloutElement = SELECT
+	(IfcAnnotationCurveOccurrence
+	,IfcAnnotationTextOccurrence
+	,IfcAnnotationSymbolOccurrence);
+END_TYPE;
+
+TYPE IfcFillAreaStyleTileShapeSelect = SELECT
+	(IfcFillAreaStyleTileSymbolWithStyle);
+END_TYPE;
+
+TYPE IfcFillStyleSelect = SELECT
+	(IfcFillAreaStyleHatching
+	,IfcFillAreaStyleTiles
+	,IfcColour
+	,IfcExternallyDefinedHatchStyle);
+END_TYPE;
+
+TYPE IfcGeometricSetSelect = SELECT
+	(IfcPoint
+	,IfcCurve
+	,IfcSurface);
+END_TYPE;
+
+TYPE IfcHatchLineDistanceSelect = SELECT
+	(IfcOneDirectionRepeatFactor
+	,IfcPositiveLengthMeasure);
+END_TYPE;
+
+TYPE IfcLayeredItem = SELECT
+	(IfcRepresentationItem
+	,IfcRepresentation);
+END_TYPE;
+
+TYPE IfcLibrarySelect = SELECT
+	(IfcLibraryReference
+	,IfcLibraryInformation);
+END_TYPE;
+
+TYPE IfcLightDistributionDataSourceSelect = SELECT
+	(IfcExternalReference
+	,IfcLightIntensityDistribution);
+END_TYPE;
+
+TYPE IfcMaterialSelect = SELECT
+	(IfcMaterial
+	,IfcMaterialList
+	,IfcMaterialLayerSetUsage
+	,IfcMaterialLayerSet
+	,IfcMaterialLayer);
+END_TYPE;
+
+TYPE IfcMeasureValue = SELECT
+	(IfcVolumeMeasure
+	,IfcTimeMeasure
+	,IfcThermodynamicTemperatureMeasure
+	,IfcSolidAngleMeasure
+	,IfcPositiveRatioMeasure
+	,IfcRatioMeasure
+	,IfcPositivePlaneAngleMeasure
+	,IfcPlaneAngleMeasure
+	,IfcParameterValue
+	,IfcNumericMeasure
+	,IfcMassMeasure
+	,IfcPositiveLengthMeasure
+	,IfcLengthMeasure
+	,IfcElectricCurrentMeasure
+	,IfcDescriptiveMeasure
+	,IfcCountMeasure
+	,IfcContextDependentMeasure
+	,IfcAreaMeasure
+	,IfcAmountOfSubstanceMeasure
+	,IfcLuminousIntensityMeasure
+	,IfcNormalisedRatioMeasure
+	,IfcComplexNumber);
+END_TYPE;
+
+TYPE IfcMetricValueSelect = SELECT
+	(IfcDateTimeSelect
+	,IfcMeasureWithUnit
+	,IfcTable
+	,IfcText
+	,IfcTimeSeries
+	,IfcCostValue);
+END_TYPE;
+
+TYPE IfcObjectReferenceSelect = SELECT
+	(IfcMaterial
+	,IfcPerson
+	,IfcDateAndTime
+	,IfcMaterialList
+	,IfcOrganization
+	,IfcCalendarDate
+	,IfcLocalTime
+	,IfcPersonAndOrganization
+	,IfcMaterialLayer
+	,IfcExternalReference
+	,IfcTimeSeries
+	,IfcAddress
+	,IfcAppliedValue);
+END_TYPE;
+
+TYPE IfcOrientationSelect = SELECT
+	(IfcPlaneAngleMeasure
+	,IfcDirection);
+END_TYPE;
+
+TYPE IfcPointOrVertexPoint = SELECT
+	(IfcPoint
+	,IfcVertexPoint);
+END_TYPE;
+
+TYPE IfcPresentationStyleSelect = SELECT
+	(IfcNullStyle
+	,IfcCurveStyle
+	,IfcSymbolStyle
+	,IfcFillAreaStyle
+	,IfcTextStyle
+	,IfcSurfaceStyle);
+END_TYPE;
+
+TYPE IfcShell = SELECT
+	(IfcClosedShell
+	,IfcOpenShell);
+END_TYPE;
+
+TYPE IfcSimpleValue = SELECT
+	(IfcInteger
+	,IfcReal
+	,IfcBoolean
+	,IfcIdentifier
+	,IfcText
+	,IfcLabel
+	,IfcLogical);
+END_TYPE;
+
+TYPE IfcSizeSelect = SELECT
+	(IfcRatioMeasure
+	,IfcLengthMeasure
+	,IfcDescriptiveMeasure
+	,IfcPositiveLengthMeasure
+	,IfcNormalisedRatioMeasure
+	,IfcPositiveRatioMeasure);
+END_TYPE;
+
+TYPE IfcSpecularHighlightSelect = SELECT
+	(IfcSpecularExponent
+	,IfcSpecularRoughness);
+END_TYPE;
+
+TYPE IfcStructuralActivityAssignmentSelect = SELECT
+	(IfcStructuralItem
+	,IfcElement);
+END_TYPE;
+
+TYPE IfcSurfaceOrFaceSurface = SELECT
+	(IfcSurface
+	,IfcFaceSurface
+	,IfcFaceBasedSurfaceModel);
+END_TYPE;
+
+TYPE IfcSurfaceStyleElementSelect = SELECT
+	(IfcSurfaceStyleShading
+	,IfcSurfaceStyleLighting
+	,IfcSurfaceStyleWithTextures
+	,IfcExternallyDefinedSurfaceStyle
+	,IfcSurfaceStyleRefraction);
+END_TYPE;
+
+TYPE IfcSymbolStyleSelect = SELECT
+	(IfcColour);
+END_TYPE;
+
+TYPE IfcTextFontSelect = SELECT
+	(IfcPreDefinedTextFont
+	,IfcExternallyDefinedTextFont);
+END_TYPE;
+
+TYPE IfcTextStyleSelect = SELECT
+	(IfcTextStyleWithBoxCharacteristics
+	,IfcTextStyleTextModel);
+END_TYPE;
+
+TYPE IfcTrimmingSelect = SELECT
+	(IfcCartesianPoint
+	,IfcParameterValue);
+END_TYPE;
+
+TYPE IfcUnit = SELECT
+	(IfcDerivedUnit
+	,IfcNamedUnit
+	,IfcMonetaryUnit);
+END_TYPE;
+
+TYPE IfcValue = SELECT
+	(IfcMeasureValue
+	,IfcSimpleValue
+	,IfcDerivedMeasureValue);
+END_TYPE;
+
+TYPE IfcVectorOrDirection = SELECT
+	(IfcDirection
+	,IfcVector);
+END_TYPE;
+
+ENTITY Ifc2DCompositeCurve
+ SUBTYPE OF (IfcCompositeCurve);
+ WHERE
+	WR1 : SELF\IfcCompositeCurve.ClosedCurve;
+	WR2 : SELF\IfcCurve.Dim = 2;
+END_ENTITY;
+
+ENTITY IfcActionRequest
+ SUBTYPE OF (IfcControl);
+	RequestID : IfcIdentifier;
+ UNIQUE
+	UR2 : RequestID;
+END_ENTITY;
+
+ENTITY IfcActor
+ SUPERTYPE OF (ONEOF
+	(IfcOccupant))
+ SUBTYPE OF (IfcObject);
+	TheActor : IfcActorSelect;
+ INVERSE
+	IsActingUpon : SET [0:?] OF IfcRelAssignsToActor FOR RelatingActor;
+END_ENTITY;
+
+ENTITY IfcActorRole;
+	Role : IfcRoleEnum;
+	UserDefinedRole : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+ WHERE
+	WR1 : (Role <> IfcRoleEnum.USERDEFINED) OR
+            ((Role = IfcRoleEnum.USERDEFINED) AND
+              EXISTS(SELF.UserDefinedRole));
+END_ENTITY;
+
+ENTITY IfcActuatorType
+ SUBTYPE OF (IfcDistributionControlElementType);
+	PredefinedType : IfcActuatorTypeEnum;
+END_ENTITY;
+
+ENTITY IfcAddress
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcPostalAddress
+	,IfcTelecomAddress));
+	Purpose : OPTIONAL IfcAddressTypeEnum;
+	Description : OPTIONAL IfcText;
+	UserDefinedPurpose : OPTIONAL IfcLabel;
+ INVERSE
+	OfPerson : SET [0:?] OF IfcPerson FOR Addresses;
+	OfOrganization : SET [0:?] OF IfcOrganization FOR Addresses;
+ WHERE
+	WR1 : (NOT(EXISTS(Purpose))) OR
+            ((Purpose <> IfcAddressTypeEnum.USERDEFINED) OR
+            ((Purpose = IfcAddressTypeEnum.USERDEFINED) AND
+              EXISTS(SELF.UserDefinedPurpose)));
+END_ENTITY;
+
+ENTITY IfcAirTerminalBoxType
+ SUBTYPE OF (IfcFlowControllerType);
+	PredefinedType : IfcAirTerminalBoxTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcAirTerminalBoxTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcAirTerminalBoxTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcAirTerminalType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcAirTerminalTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcAirTerminalTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcAirTerminalTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcAirToAirHeatRecoveryType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcAirToAirHeatRecoveryTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcAirToAirHeatRecoveryTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcAirToAirHeatRecoveryTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcAlarmType
+ SUBTYPE OF (IfcDistributionControlElementType);
+	PredefinedType : IfcAlarmTypeEnum;
+END_ENTITY;
+
+ENTITY IfcAngularDimension
+ SUBTYPE OF (IfcDimensionCurveDirectedCallout);
+END_ENTITY;
+
+ENTITY IfcAnnotation
+ SUBTYPE OF (IfcProduct);
+ INVERSE
+	ContainedInStructure : SET [0:1] OF IfcRelContainedInSpatialStructure FOR RelatedElements;
+END_ENTITY;
+
+ENTITY IfcAnnotationCurveOccurrence
+ SUPERTYPE OF (ONEOF
+	(IfcDimensionCurve
+	,IfcProjectionCurve))
+ SUBTYPE OF (IfcAnnotationOccurrence);
+ WHERE
+	WR31 : NOT(EXISTS(SELF\IfcStyledItem.Item)) OR
+             ('IFC2X3.IFCCURVE' IN TYPEOF (SELF\IfcStyledItem.Item));
+END_ENTITY;
+
+ENTITY IfcAnnotationFillArea
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	OuterBoundary : IfcCurve;
+	InnerBoundaries : OPTIONAL SET [1:?] OF IfcCurve;
+END_ENTITY;
+
+ENTITY IfcAnnotationFillAreaOccurrence
+ SUBTYPE OF (IfcAnnotationOccurrence);
+	FillStyleTarget : OPTIONAL IfcPoint;
+	GlobalOrLocal : OPTIONAL IfcGlobalOrLocalEnum;
+ WHERE
+	WR31 : NOT(EXISTS(SELF\IfcStyledItem.Item)) OR
+             ('IFC2X3.IFCANNOTATIONFILLAREA' IN TYPEOF (SELF\IfcStyledItem.Item));
+END_ENTITY;
+
+ENTITY IfcAnnotationOccurrence
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcAnnotationCurveOccurrence
+	,IfcAnnotationFillAreaOccurrence
+	,IfcAnnotationSurfaceOccurrence
+	,IfcAnnotationSymbolOccurrence
+	,IfcAnnotationTextOccurrence))
+ SUBTYPE OF (IfcStyledItem);
+END_ENTITY;
+
+ENTITY IfcAnnotationSurface
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Item : IfcGeometricRepresentationItem;
+	TextureCoordinates : OPTIONAL IfcTextureCoordinate;
+ WHERE
+	WR01 : SIZEOF([
+               'IFC2X3.IFCSURFACE',
+               'IFC2X3.IFCSHELLBASEDSURFACEMODEL',
+               'IFC2X3.IFCFACEBASEDSURFACEMODEL',
+               'IFC2X3.IFCSOLIDMODEL',
+               'IFC2X3.IFCBOOLEANRESULT',
+               'IFC2X3.IFCCSGPRIMITIVE3D'] 
+              * TYPEOF(Item)
+               ) >= 1;
+END_ENTITY;
+
+ENTITY IfcAnnotationSurfaceOccurrence
+ SUBTYPE OF (IfcAnnotationOccurrence);
+ WHERE
+	WR31 : NOT(EXISTS(SELF\IfcStyledItem.Item)) OR 
+             (SIZEOF(
+              ['IFC2X3.IFCSURFACE',
+               'IFC2X3.IFCFACEBASEDSURFACEMODEL',
+               'IFC2X3.IFCSHELLBASEDSURFACEMODEL',
+               'IFC2X3.IFCSOLIDMODEL'] *
+              TYPEOF(SELF\IfcStyledItem.Item)) > 0);
+END_ENTITY;
+
+ENTITY IfcAnnotationSymbolOccurrence
+ SUPERTYPE OF (ONEOF
+	(IfcTerminatorSymbol))
+ SUBTYPE OF (IfcAnnotationOccurrence);
+ WHERE
+	WR31 : NOT(EXISTS(SELF\IfcStyledItem.Item)) OR
+             ('IFC2X3.IFCDEFINEDSYMBOL' IN TYPEOF (SELF\IfcStyledItem.Item));
+END_ENTITY;
+
+ENTITY IfcAnnotationTextOccurrence
+ SUBTYPE OF (IfcAnnotationOccurrence);
+ WHERE
+	WR31 : NOT(EXISTS(SELF\IfcStyledItem.Item)) OR
+             ('IFC2X3.IFCTEXTLITERAL' IN TYPEOF (SELF\IfcStyledItem.Item));
+END_ENTITY;
+
+ENTITY IfcApplication;
+	ApplicationDeveloper : IfcOrganization;
+	Version : IfcLabel;
+	ApplicationFullName : IfcLabel;
+	ApplicationIdentifier : IfcIdentifier;
+ UNIQUE
+	UR1 : ApplicationIdentifier;
+	UR2 : ApplicationFullName, Version;
+END_ENTITY;
+
+ENTITY IfcAppliedValue
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCostValue
+	,IfcEnvironmentalImpactValue));
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+	AppliedValue : OPTIONAL IfcAppliedValueSelect;
+	UnitBasis : OPTIONAL IfcMeasureWithUnit;
+	ApplicableDate : OPTIONAL IfcDateTimeSelect;
+	FixedUntilDate : OPTIONAL IfcDateTimeSelect;
+ INVERSE
+	ValuesReferenced : SET [0:?] OF IfcReferencesValueDocument FOR ReferencingValues;
+	ValueOfComponents : SET [0:?] OF IfcAppliedValueRelationship FOR ComponentOfTotal;
+	IsComponentIn : SET [0:?] OF IfcAppliedValueRelationship FOR Components;
+ WHERE
+	WR1 : EXISTS (AppliedValue) OR 
+            EXISTS (ValueOfComponents);
+END_ENTITY;
+
+ENTITY IfcAppliedValueRelationship;
+	ComponentOfTotal : IfcAppliedValue;
+	Components : SET [1:?] OF IfcAppliedValue;
+	ArithmeticOperator : IfcArithmeticOperatorEnum;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+END_ENTITY;
+
+ENTITY IfcApproval;
+	Description : OPTIONAL IfcText;
+	ApprovalDateTime : IfcDateTimeSelect;
+	ApprovalStatus : OPTIONAL IfcLabel;
+	ApprovalLevel : OPTIONAL IfcLabel;
+	ApprovalQualifier : OPTIONAL IfcText;
+	Name : IfcLabel;
+	Identifier : IfcIdentifier;
+ INVERSE
+	Actors : SET [0:?] OF IfcApprovalActorRelationship FOR Approval;
+	IsRelatedWith : SET [0:?] OF IfcApprovalRelationship FOR RelatedApproval;
+	Relates : SET [0:?] OF IfcApprovalRelationship FOR RelatingApproval;
+END_ENTITY;
+
+ENTITY IfcApprovalActorRelationship;
+	Actor : IfcActorSelect;
+	Approval : IfcApproval;
+	Role : IfcActorRole;
+END_ENTITY;
+
+ENTITY IfcApprovalPropertyRelationship;
+	ApprovedProperties : SET [1:?] OF IfcProperty;
+	Approval : IfcApproval;
+END_ENTITY;
+
+ENTITY IfcApprovalRelationship;
+	RelatedApproval : IfcApproval;
+	RelatingApproval : IfcApproval;
+	Description : OPTIONAL IfcText;
+	Name : IfcLabel;
+END_ENTITY;
+
+ENTITY IfcArbitraryClosedProfileDef
+ SUPERTYPE OF (ONEOF
+	(IfcArbitraryProfileDefWithVoids))
+ SUBTYPE OF (IfcProfileDef);
+	OuterCurve : IfcCurve;
+ WHERE
+	WR1 : OuterCurve.Dim = 2;
+	WR2 : NOT('IFC2X3.IFCLINE' IN TYPEOF(OuterCurve));
+	WR3 : NOT('IFC2X3.IFCOFFSETCURVE2D' IN TYPEOF(OuterCurve));
+END_ENTITY;
+
+ENTITY IfcArbitraryOpenProfileDef
+ SUPERTYPE OF (ONEOF
+	(IfcCenterLineProfileDef))
+ SUBTYPE OF (IfcProfileDef);
+	Curve : IfcBoundedCurve;
+ WHERE
+	WR11 : ('IFC2X3.IFCCENTERLINEPROFILEDEF' IN TYPEOF(SELF)) OR 
+              (SELF\IfcProfileDef.ProfileType = IfcProfileTypeEnum.CURVE);
+	WR12 : Curve.Dim = 2;
+END_ENTITY;
+
+ENTITY IfcArbitraryProfileDefWithVoids
+ SUBTYPE OF (IfcArbitraryClosedProfileDef);
+	InnerCurves : SET [1:?] OF IfcCurve;
+ WHERE
+	WR1 : SELF\IfcProfileDef.ProfileType = AREA;
+	WR2 : SIZEOF(QUERY(temp <* InnerCurves | temp.Dim <> 2)) = 0;
+	WR3 : SIZEOF(QUERY(temp <* InnerCurves | 'IFC2X3.IFCLINE' IN TYPEOF(temp))) = 0;
+END_ENTITY;
+
+ENTITY IfcAsset
+ SUBTYPE OF (IfcGroup);
+	AssetID : IfcIdentifier;
+	OriginalValue : IfcCostValue;
+	CurrentValue : IfcCostValue;
+	TotalReplacementCost : IfcCostValue;
+	Owner : IfcActorSelect;
+	User : IfcActorSelect;
+	ResponsiblePerson : IfcPerson;
+	IncorporationDate : IfcCalendarDate;
+	DepreciatedValue : IfcCostValue;
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcGroup.IsGroupedBy.RelatedObjects | NOT('IFC2X3.IFCELEMENT' IN TYPEOF(Temp)))) = 0;
+END_ENTITY;
+
+ENTITY IfcAsymmetricIShapeProfileDef
+ SUBTYPE OF (IfcIShapeProfileDef);
+	TopFlangeWidth : IfcPositiveLengthMeasure;
+	TopFlangeThickness : OPTIONAL IfcPositiveLengthMeasure;
+	TopFlangeFilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+	CentreOfGravityInY : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcAxis1Placement
+ SUBTYPE OF (IfcPlacement);
+	Axis : OPTIONAL IfcDirection;
+ DERIVE
+	Z : IfcDirection := NVL (IfcNormalise(Axis), IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0,0.0,1.0]));
+ WHERE
+	WR1 : (NOT (EXISTS (Axis))) OR (Axis.Dim = 3);
+	WR2 : SELF\IfcPlacement.Location.Dim = 3;
+END_ENTITY;
+
+ENTITY IfcAxis2Placement2D
+ SUBTYPE OF (IfcPlacement);
+	RefDirection : OPTIONAL IfcDirection;
+ DERIVE
+	P : LIST [2:2] OF IfcDirection := IfcBuild2Axes(RefDirection);
+ WHERE
+	WR1 : (NOT (EXISTS (RefDirection))) OR (RefDirection.Dim = 2);
+	WR2 : SELF\IfcPlacement.Location.Dim = 2;
+END_ENTITY;
+
+ENTITY IfcAxis2Placement3D
+ SUBTYPE OF (IfcPlacement);
+	Axis : OPTIONAL IfcDirection;
+	RefDirection : OPTIONAL IfcDirection;
+ DERIVE
+	P : LIST [3:3] OF IfcDirection := IfcBuildAxes(Axis, RefDirection);
+ WHERE
+	WR1 : SELF\IfcPlacement.Location.Dim = 3;
+	WR2 : (NOT (EXISTS (Axis))) OR (Axis.Dim = 3);
+	WR3 : (NOT (EXISTS (RefDirection))) OR (RefDirection.Dim = 3);
+	WR4 : (NOT (EXISTS (Axis))) OR (NOT (EXISTS (RefDirection))) OR (IfcCrossProduct(Axis,RefDirection).Magnitude > 0.0);
+	WR5 : NOT ((EXISTS (Axis)) XOR (EXISTS (RefDirection)));
+END_ENTITY;
+
+ENTITY IfcBSplineCurve
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBezierCurve))
+ SUBTYPE OF (IfcBoundedCurve);
+	Degree : INTEGER;
+	ControlPointsList : LIST [2:?] OF IfcCartesianPoint;
+	CurveForm : IfcBSplineCurveForm;
+	ClosedCurve : LOGICAL;
+	SelfIntersect : LOGICAL;
+ DERIVE
+	ControlPoints : ARRAY [0:255] OF IfcCartesianPoint := IfcListToArray(ControlPointsList,0,UpperIndexOnControlPoints);
+	UpperIndexOnControlPoints : INTEGER := (SIZEOF(ControlPointsList) - 1);
+ WHERE
+	WR41 : SIZEOF(QUERY(Temp <* ControlPointsList |
+               Temp.Dim <> ControlPointsList[1].Dim))
+             = 0;
+END_ENTITY;
+
+ENTITY IfcBeam
+ SUBTYPE OF (IfcBuildingElement);
+END_ENTITY;
+
+ENTITY IfcBeamType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcBeamTypeEnum;
+END_ENTITY;
+
+ENTITY IfcBezierCurve
+ SUPERTYPE OF (ONEOF
+	(IfcRationalBezierCurve))
+ SUBTYPE OF (IfcBSplineCurve);
+END_ENTITY;
+
+ENTITY IfcBlobTexture
+ SUBTYPE OF (IfcSurfaceTexture);
+	RasterFormat : IfcIdentifier;
+	RasterCode : BOOLEAN;
+ WHERE
+	WR11 : SELF.RasterFormat IN ['BMP', 'JPG', 'GIF', 'PNG'];
+END_ENTITY;
+
+ENTITY IfcBlock
+ SUBTYPE OF (IfcCsgPrimitive3D);
+	XLength : IfcPositiveLengthMeasure;
+	YLength : IfcPositiveLengthMeasure;
+	ZLength : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcBoilerType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcBoilerTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcBoilerTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcBoilerTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcBooleanClippingResult
+ SUBTYPE OF (IfcBooleanResult);
+ WHERE
+	WR1 : ('IFC2X3.IFCSWEPTAREASOLID' IN TYPEOF(FirstOperand)) OR ('IFC2X3.IFCBOOLEANCLIPPINGRESULT' IN TYPEOF(FirstOperand));
+	WR2 : ('IFC2X3.IFCHALFSPACESOLID' IN TYPEOF(SecondOperand));
+	WR3 : Operator = DIFFERENCE;
+END_ENTITY;
+
+ENTITY IfcBooleanResult
+ SUPERTYPE OF (ONEOF
+	(IfcBooleanClippingResult))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Operator : IfcBooleanOperator;
+	FirstOperand : IfcBooleanOperand;
+	SecondOperand : IfcBooleanOperand;
+ DERIVE
+	Dim : IfcDimensionCount := FirstOperand.Dim;
+ WHERE
+	WR1 : FirstOperand.Dim = SecondOperand.Dim;
+END_ENTITY;
+
+ENTITY IfcBoundaryCondition
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBoundaryEdgeCondition
+	,IfcBoundaryFaceCondition
+	,IfcBoundaryNodeCondition));
+	Name : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcBoundaryEdgeCondition
+ SUBTYPE OF (IfcBoundaryCondition);
+	LinearStiffnessByLengthX : OPTIONAL IfcModulusOfLinearSubgradeReactionMeasure;
+	LinearStiffnessByLengthY : OPTIONAL IfcModulusOfLinearSubgradeReactionMeasure;
+	LinearStiffnessByLengthZ : OPTIONAL IfcModulusOfLinearSubgradeReactionMeasure;
+	RotationalStiffnessByLengthX : OPTIONAL IfcModulusOfRotationalSubgradeReactionMeasure;
+	RotationalStiffnessByLengthY : OPTIONAL IfcModulusOfRotationalSubgradeReactionMeasure;
+	RotationalStiffnessByLengthZ : OPTIONAL IfcModulusOfRotationalSubgradeReactionMeasure;
+END_ENTITY;
+
+ENTITY IfcBoundaryFaceCondition
+ SUBTYPE OF (IfcBoundaryCondition);
+	LinearStiffnessByAreaX : OPTIONAL IfcModulusOfSubgradeReactionMeasure;
+	LinearStiffnessByAreaY : OPTIONAL IfcModulusOfSubgradeReactionMeasure;
+	LinearStiffnessByAreaZ : OPTIONAL IfcModulusOfSubgradeReactionMeasure;
+END_ENTITY;
+
+ENTITY IfcBoundaryNodeCondition
+ SUPERTYPE OF (ONEOF
+	(IfcBoundaryNodeConditionWarping))
+ SUBTYPE OF (IfcBoundaryCondition);
+	LinearStiffnessX : OPTIONAL IfcLinearStiffnessMeasure;
+	LinearStiffnessY : OPTIONAL IfcLinearStiffnessMeasure;
+	LinearStiffnessZ : OPTIONAL IfcLinearStiffnessMeasure;
+	RotationalStiffnessX : OPTIONAL IfcRotationalStiffnessMeasure;
+	RotationalStiffnessY : OPTIONAL IfcRotationalStiffnessMeasure;
+	RotationalStiffnessZ : OPTIONAL IfcRotationalStiffnessMeasure;
+END_ENTITY;
+
+ENTITY IfcBoundaryNodeConditionWarping
+ SUBTYPE OF (IfcBoundaryNodeCondition);
+	WarpingStiffness : OPTIONAL IfcWarpingMomentMeasure;
+END_ENTITY;
+
+ENTITY IfcBoundedCurve
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBSplineCurve
+	,IfcCompositeCurve
+	,IfcPolyline
+	,IfcTrimmedCurve))
+ SUBTYPE OF (IfcCurve);
+END_ENTITY;
+
+ENTITY IfcBoundedSurface
+ SUPERTYPE OF (ONEOF
+	(IfcCurveBoundedPlane
+	,IfcRectangularTrimmedSurface))
+ SUBTYPE OF (IfcSurface);
+END_ENTITY;
+
+ENTITY IfcBoundingBox
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Corner : IfcCartesianPoint;
+	XDim : IfcPositiveLengthMeasure;
+	YDim : IfcPositiveLengthMeasure;
+	ZDim : IfcPositiveLengthMeasure;
+ DERIVE
+	Dim : IfcDimensionCount := 3;
+END_ENTITY;
+
+ENTITY IfcBoxedHalfSpace
+ SUBTYPE OF (IfcHalfSpaceSolid);
+	Enclosure : IfcBoundingBox;
+ WHERE
+	WR1 : NOT ('IFC2X3.IFCCURVEBOUNDEDPLANE' IN TYPEOF(SELF\IfcHalfSpaceSolid.BaseSurface));
+END_ENTITY;
+
+ENTITY IfcBuilding
+ SUBTYPE OF (IfcSpatialStructureElement);
+	ElevationOfRefHeight : OPTIONAL IfcLengthMeasure;
+	ElevationOfTerrain : OPTIONAL IfcLengthMeasure;
+	BuildingAddress : OPTIONAL IfcPostalAddress;
+END_ENTITY;
+
+ENTITY IfcBuildingElement
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBeam
+	,IfcBuildingElementComponent
+	,IfcBuildingElementProxy
+	,IfcColumn
+	,IfcCovering
+	,IfcCurtainWall
+	,IfcDoor
+	,IfcFooting
+	,IfcMember
+	,IfcPile
+	,IfcPlate
+	,IfcRailing
+	,IfcRamp
+	,IfcRampFlight
+	,IfcRoof
+	,IfcSlab
+	,IfcStair
+	,IfcStairFlight
+	,IfcWall
+	,IfcWindow))
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcBuildingElementComponent
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBuildingElementPart
+	,IfcReinforcingElement))
+ SUBTYPE OF (IfcBuildingElement);
+END_ENTITY;
+
+ENTITY IfcBuildingElementPart
+ SUBTYPE OF (IfcBuildingElementComponent);
+END_ENTITY;
+
+ENTITY IfcBuildingElementProxy
+ SUBTYPE OF (IfcBuildingElement);
+	CompositionType : OPTIONAL IfcElementCompositionEnum;
+ WHERE
+	WR1 : EXISTS(SELF\IfcRoot.Name);
+END_ENTITY;
+
+ENTITY IfcBuildingElementProxyType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcBuildingElementProxyTypeEnum;
+END_ENTITY;
+
+ENTITY IfcBuildingElementType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBeamType
+	,IfcBuildingElementProxyType
+	,IfcColumnType
+	,IfcCoveringType
+	,IfcCurtainWallType
+	,IfcMemberType
+	,IfcPlateType
+	,IfcRailingType
+	,IfcRampFlightType
+	,IfcSlabType
+	,IfcStairFlightType
+	,IfcWallType))
+ SUBTYPE OF (IfcElementType);
+END_ENTITY;
+
+ENTITY IfcBuildingStorey
+ SUBTYPE OF (IfcSpatialStructureElement);
+	Elevation : OPTIONAL IfcLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcCShapeProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	Depth : IfcPositiveLengthMeasure;
+	Width : IfcPositiveLengthMeasure;
+	WallThickness : IfcPositiveLengthMeasure;
+	Girth : IfcPositiveLengthMeasure;
+	InternalFilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+	CentreOfGravityInX : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR1 : Girth < (Depth / 2.);
+	WR2 : NOT(EXISTS(InternalFilletRadius)) OR
+            ((InternalFilletRadius <= Width/2.) AND (InternalFilletRadius <= Depth/2.));
+	WR3 : (WallThickness < Width/2.) AND (WallThickness < Depth/2.);
+END_ENTITY;
+
+ENTITY IfcCableCarrierFittingType
+ SUBTYPE OF (IfcFlowFittingType);
+	PredefinedType : IfcCableCarrierFittingTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcCableCarrierFittingTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcCableCarrierFittingTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcCableCarrierSegmentType
+ SUBTYPE OF (IfcFlowSegmentType);
+	PredefinedType : IfcCableCarrierSegmentTypeEnum;
+END_ENTITY;
+
+ENTITY IfcCableSegmentType
+ SUBTYPE OF (IfcFlowSegmentType);
+	PredefinedType : IfcCableSegmentTypeEnum;
+END_ENTITY;
+
+ENTITY IfcCalendarDate;
+	DayComponent : IfcDayInMonthNumber;
+	MonthComponent : IfcMonthInYearNumber;
+	YearComponent : IfcYearNumber;
+ WHERE
+	WR21 : IfcValidCalendarDate (SELF);
+END_ENTITY;
+
+ENTITY IfcCartesianPoint
+ SUBTYPE OF (IfcPoint);
+	Coordinates : LIST [1:3] OF IfcLengthMeasure;
+ DERIVE
+	Dim : IfcDimensionCount := HIINDEX(Coordinates);
+ WHERE
+	WR1 : HIINDEX(Coordinates) >= 2;
+END_ENTITY;
+
+ENTITY IfcCartesianTransformationOperator
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCartesianTransformationOperator2D
+	,IfcCartesianTransformationOperator3D))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Axis1 : OPTIONAL IfcDirection;
+	Axis2 : OPTIONAL IfcDirection;
+	LocalOrigin : IfcCartesianPoint;
+	Scale : OPTIONAL REAL;
+ DERIVE
+	Scl : REAL := NVL(Scale, 1.0);
+	Dim : IfcDimensionCount := LocalOrigin.Dim;
+ WHERE
+	WR1 : Scl > 0.0;
+END_ENTITY;
+
+ENTITY IfcCartesianTransformationOperator2D
+ SUPERTYPE OF (ONEOF
+	(IfcCartesianTransformationOperator2DnonUniform))
+ SUBTYPE OF (IfcCartesianTransformationOperator);
+ DERIVE
+	U : LIST [2:2] OF IfcDirection := IfcBaseAxis(2,SELF\IfcCartesianTransformationOperator.Axis1,
+          SELF\IfcCartesianTransformationOperator.Axis2,?);
+ WHERE
+	WR1 : SELF\IfcCartesianTransformationOperator.Dim = 2;
+	WR2 : NOT(EXISTS(SELF\IfcCartesianTransformationOperator.Axis1)) OR 
+            (SELF\IfcCartesianTransformationOperator.Axis1.Dim = 2);
+	WR3 : NOT(EXISTS(SELF\IfcCartesianTransformationOperator.Axis2)) OR 
+            (SELF\IfcCartesianTransformationOperator.Axis2.Dim = 2);
+END_ENTITY;
+
+ENTITY IfcCartesianTransformationOperator2DnonUniform
+ SUBTYPE OF (IfcCartesianTransformationOperator2D);
+	Scale2 : OPTIONAL REAL;
+ DERIVE
+	Scl2 : REAL := NVL(Scale2, SELF\IfcCartesianTransformationOperator.Scl);
+ WHERE
+	WR1 : Scl2 > 0.0;
+END_ENTITY;
+
+ENTITY IfcCartesianTransformationOperator3D
+ SUPERTYPE OF (ONEOF
+	(IfcCartesianTransformationOperator3DnonUniform))
+ SUBTYPE OF (IfcCartesianTransformationOperator);
+	Axis3 : OPTIONAL IfcDirection;
+ DERIVE
+	U : LIST [3:3] OF IfcDirection := IfcBaseAxis(3,SELF\IfcCartesianTransformationOperator.Axis1,
+              SELF\IfcCartesianTransformationOperator.Axis2,Axis3);
+ WHERE
+	WR1 : SELF\IfcCartesianTransformationOperator.Dim = 3;
+	WR2 : NOT(EXISTS(SELF\IfcCartesianTransformationOperator.Axis1)) OR 
+            (SELF\IfcCartesianTransformationOperator.Axis1.Dim = 3);
+	WR3 : NOT(EXISTS(SELF\IfcCartesianTransformationOperator.Axis2)) OR 
+            (SELF\IfcCartesianTransformationOperator.Axis2.Dim = 3);
+	WR4 : NOT(EXISTS(Axis3)) OR (Axis3.Dim = 3);
+END_ENTITY;
+
+ENTITY IfcCartesianTransformationOperator3DnonUniform
+ SUBTYPE OF (IfcCartesianTransformationOperator3D);
+	Scale2 : OPTIONAL REAL;
+	Scale3 : OPTIONAL REAL;
+ DERIVE
+	Scl2 : REAL := NVL(Scale2, SELF\IfcCartesianTransformationOperator.Scl);
+	Scl3 : REAL := NVL(Scale3, SELF\IfcCartesianTransformationOperator.Scl);
+ WHERE
+	WR1 : Scl2 > 0.0;
+	WR2 : Scl3 > 0.0;
+END_ENTITY;
+
+ENTITY IfcCenterLineProfileDef
+ SUBTYPE OF (IfcArbitraryOpenProfileDef);
+	Thickness : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcChamferEdgeFeature
+ SUBTYPE OF (IfcEdgeFeature);
+	Width : OPTIONAL IfcPositiveLengthMeasure;
+	Height : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcChillerType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcChillerTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcChillerTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcChillerTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcCircle
+ SUBTYPE OF (IfcConic);
+	Radius : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcCircleHollowProfileDef
+ SUBTYPE OF (IfcCircleProfileDef);
+	WallThickness : IfcPositiveLengthMeasure;
+ WHERE
+	WR1 : WallThickness < SELF\IfcCircleProfileDef.Radius;
+END_ENTITY;
+
+ENTITY IfcCircleProfileDef
+ SUPERTYPE OF (ONEOF
+	(IfcCircleHollowProfileDef))
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	Radius : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcClassification;
+	Source : IfcLabel;
+	Edition : IfcLabel;
+	EditionDate : OPTIONAL IfcCalendarDate;
+	Name : IfcLabel;
+ INVERSE
+	Contains : SET [0:?] OF IfcClassificationItem FOR ItemOf;
+END_ENTITY;
+
+ENTITY IfcClassificationItem;
+	Notation : IfcClassificationNotationFacet;
+	ItemOf : OPTIONAL IfcClassification;
+	Title : IfcLabel;
+ INVERSE
+	IsClassifiedItemIn : SET [0:1] OF IfcClassificationItemRelationship FOR RelatedItems;
+	IsClassifyingItemIn : SET [0:1] OF IfcClassificationItemRelationship FOR RelatingItem;
+END_ENTITY;
+
+ENTITY IfcClassificationItemRelationship;
+	RelatingItem : IfcClassificationItem;
+	RelatedItems : SET [1:?] OF IfcClassificationItem;
+END_ENTITY;
+
+ENTITY IfcClassificationNotation;
+	NotationFacets : SET [1:?] OF IfcClassificationNotationFacet;
+END_ENTITY;
+
+ENTITY IfcClassificationNotationFacet;
+	NotationValue : IfcLabel;
+END_ENTITY;
+
+ENTITY IfcClassificationReference
+ SUBTYPE OF (IfcExternalReference);
+	ReferencedSource : OPTIONAL IfcClassification;
+END_ENTITY;
+
+ENTITY IfcClosedShell
+ SUBTYPE OF (IfcConnectedFaceSet);
+END_ENTITY;
+
+ENTITY IfcCoilType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcCoilTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcCoilTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcCoilTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcColourRgb
+ SUBTYPE OF (IfcColourSpecification);
+	Red : IfcNormalisedRatioMeasure;
+	Green : IfcNormalisedRatioMeasure;
+	Blue : IfcNormalisedRatioMeasure;
+END_ENTITY;
+
+ENTITY IfcColourSpecification
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcColourRgb));
+	Name : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcColumn
+ SUBTYPE OF (IfcBuildingElement);
+END_ENTITY;
+
+ENTITY IfcColumnType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcColumnTypeEnum;
+END_ENTITY;
+
+ENTITY IfcComplexProperty
+ SUBTYPE OF (IfcProperty);
+	UsageName : IfcIdentifier;
+	HasProperties : SET [1:?] OF IfcProperty;
+ WHERE
+	WR21 : SIZEOF(QUERY(temp <* HasProperties | SELF :=: temp)) = 0;
+	WR22 : IfcUniquePropertyName(HasProperties);
+END_ENTITY;
+
+ENTITY IfcCompositeCurve
+ SUPERTYPE OF (ONEOF
+	(Ifc2DCompositeCurve))
+ SUBTYPE OF (IfcBoundedCurve);
+	Segments : LIST [1:?] OF IfcCompositeCurveSegment;
+	SelfIntersect : LOGICAL;
+ DERIVE
+	NSegments : INTEGER := SIZEOF(Segments);
+	ClosedCurve : LOGICAL := Segments[NSegments].Transition <> Discontinuous;
+ WHERE
+	WR41 : ((NOT ClosedCurve) AND (SIZEOF(QUERY(Temp <* Segments | Temp.Transition = Discontinuous)) = 1)) OR ((ClosedCurve) AND (SIZEOF(QUERY(Temp <* Segments | Temp.Transition = Discontinuous)) = 0));
+	WR42 : SIZEOF( QUERY( Temp <* Segments | Temp.Dim <> Segments[1].Dim)) = 0;
+END_ENTITY;
+
+ENTITY IfcCompositeCurveSegment
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Transition : IfcTransitionCode;
+	SameSense : BOOLEAN;
+	ParentCurve : IfcCurve;
+ DERIVE
+	Dim : IfcDimensionCount := ParentCurve.Dim;
+ INVERSE
+	UsingCurves : SET [1:?] OF IfcCompositeCurve FOR Segments;
+ WHERE
+	WR1 : ('IFC2X3.IFCBOUNDEDCURVE' IN TYPEOF(ParentCurve));
+END_ENTITY;
+
+ENTITY IfcCompositeProfileDef
+ SUBTYPE OF (IfcProfileDef);
+	Profiles : SET [2:?] OF IfcProfileDef;
+	Label : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : SIZEOF(QUERY(temp <* Profiles | temp.ProfileType <> Profiles[1].ProfileType)) = 0;
+	WR2 : SIZEOF(QUERY(temp <* Profiles | 'IFC2X3.IFCCOMPOSITEPROFILEDEF' IN TYPEOF(temp))) = 0;
+END_ENTITY;
+
+ENTITY IfcCompressorType
+ SUBTYPE OF (IfcFlowMovingDeviceType);
+	PredefinedType : IfcCompressorTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcCompressorTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcCompressorTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcCondenserType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcCondenserTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcCondenserTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcCondenserTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcCondition
+ SUBTYPE OF (IfcGroup);
+END_ENTITY;
+
+ENTITY IfcConditionCriterion
+ SUBTYPE OF (IfcControl);
+	Criterion : IfcConditionCriterionSelect;
+	CriterionDateTime : IfcDateTimeSelect;
+ WHERE
+	WR1 : EXISTS(SELF\IfcRoot.Name);
+END_ENTITY;
+
+ENTITY IfcConic
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCircle
+	,IfcEllipse))
+ SUBTYPE OF (IfcCurve);
+	Position : IfcAxis2Placement;
+END_ENTITY;
+
+ENTITY IfcConnectedFaceSet
+ SUPERTYPE OF (ONEOF
+	(IfcClosedShell
+	,IfcOpenShell))
+ SUBTYPE OF (IfcTopologicalRepresentationItem);
+	CfsFaces : SET [1:?] OF IfcFace;
+END_ENTITY;
+
+ENTITY IfcConnectionCurveGeometry
+ SUBTYPE OF (IfcConnectionGeometry);
+	CurveOnRelatingElement : IfcCurveOrEdgeCurve;
+	CurveOnRelatedElement : OPTIONAL IfcCurveOrEdgeCurve;
+END_ENTITY;
+
+ENTITY IfcConnectionGeometry
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcConnectionCurveGeometry
+	,IfcConnectionPointGeometry
+	,IfcConnectionPortGeometry
+	,IfcConnectionSurfaceGeometry));
+END_ENTITY;
+
+ENTITY IfcConnectionPointEccentricity
+ SUBTYPE OF (IfcConnectionPointGeometry);
+	EccentricityInX : OPTIONAL IfcLengthMeasure;
+	EccentricityInY : OPTIONAL IfcLengthMeasure;
+	EccentricityInZ : OPTIONAL IfcLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcConnectionPointGeometry
+ SUPERTYPE OF (ONEOF
+	(IfcConnectionPointEccentricity))
+ SUBTYPE OF (IfcConnectionGeometry);
+	PointOnRelatingElement : IfcPointOrVertexPoint;
+	PointOnRelatedElement : OPTIONAL IfcPointOrVertexPoint;
+END_ENTITY;
+
+ENTITY IfcConnectionPortGeometry
+ SUBTYPE OF (IfcConnectionGeometry);
+	LocationAtRelatingElement : IfcAxis2Placement;
+	LocationAtRelatedElement : OPTIONAL IfcAxis2Placement;
+	ProfileOfPort : IfcProfileDef;
+END_ENTITY;
+
+ENTITY IfcConnectionSurfaceGeometry
+ SUBTYPE OF (IfcConnectionGeometry);
+	SurfaceOnRelatingElement : IfcSurfaceOrFaceSurface;
+	SurfaceOnRelatedElement : OPTIONAL IfcSurfaceOrFaceSurface;
+END_ENTITY;
+
+ENTITY IfcConstraint
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcMetric
+	,IfcObjective));
+	Name : IfcLabel;
+	Description : OPTIONAL IfcText;
+	ConstraintGrade : IfcConstraintEnum;
+	ConstraintSource : OPTIONAL IfcLabel;
+	CreatingActor : OPTIONAL IfcActorSelect;
+	CreationTime : OPTIONAL IfcDateTimeSelect;
+	UserDefinedGrade : OPTIONAL IfcLabel;
+ INVERSE
+	ClassifiedAs : SET [0:?] OF IfcConstraintClassificationRelationship FOR ClassifiedConstraint;
+	RelatesConstraints : SET [0:?] OF IfcConstraintRelationship FOR RelatingConstraint;
+	IsRelatedWith : SET [0:?] OF IfcConstraintRelationship FOR RelatedConstraints;
+	PropertiesForConstraint : SET [0:?] OF IfcPropertyConstraintRelationship FOR RelatingConstraint;
+	Aggregates : SET [0:?] OF IfcConstraintAggregationRelationship FOR RelatingConstraint;
+	IsAggregatedIn : SET [0:?] OF IfcConstraintAggregationRelationship FOR RelatedConstraints;
+ WHERE
+	WR11 : (ConstraintGrade <> IfcConstraintEnum.USERDEFINED) OR
+             ((ConstraintGrade = IfcConstraintEnum.USERDEFINED) AND EXISTS(SELF\IfcConstraint.UserDefinedGrade));
+END_ENTITY;
+
+ENTITY IfcConstraintAggregationRelationship;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+	RelatingConstraint : IfcConstraint;
+	RelatedConstraints : LIST [1:?] OF UNIQUE IfcConstraint;
+	LogicalAggregator : IfcLogicalOperatorEnum;
+ WHERE
+	WR11 : SIZEOF(QUERY(temp <* RelatedConstraints | 
+               temp :=: RelatingConstraint
+               )) = 0;
+END_ENTITY;
+
+ENTITY IfcConstraintClassificationRelationship;
+	ClassifiedConstraint : IfcConstraint;
+	RelatedClassifications : SET [1:?] OF IfcClassificationNotationSelect;
+END_ENTITY;
+
+ENTITY IfcConstraintRelationship;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+	RelatingConstraint : IfcConstraint;
+	RelatedConstraints : SET [1:?] OF IfcConstraint;
+ WHERE
+	WR11 : SIZEOF(QUERY(temp <* RelatedConstraints | temp :=: RelatingConstraint )) = 0;
+END_ENTITY;
+
+ENTITY IfcConstructionEquipmentResource
+ SUBTYPE OF (IfcConstructionResource);
+END_ENTITY;
+
+ENTITY IfcConstructionMaterialResource
+ SUBTYPE OF (IfcConstructionResource);
+	Suppliers : OPTIONAL SET [1:?] OF IfcActorSelect;
+	UsageRatio : OPTIONAL IfcRatioMeasure;
+ WHERE
+	WR1 : SIZEOF(SELF\IfcResource.ResourceOf) <=1;
+	WR2 : NOT(EXISTS(SELF\IfcResource.ResourceOf[1])) OR
+            (SELF\IfcResource.ResourceOf[1].RelatedObjectsType = IfcObjectTypeEnum.PRODUCT);
+END_ENTITY;
+
+ENTITY IfcConstructionProductResource
+ SUBTYPE OF (IfcConstructionResource);
+ WHERE
+	WR1 : SIZEOF(SELF\IfcResource.ResourceOf) <=1;
+	WR2 : NOT(EXISTS(SELF\IfcResource.ResourceOf[1])) OR
+            (SELF\IfcResource.ResourceOf[1].RelatedObjectsType = IfcObjectTypeEnum.PRODUCT);
+END_ENTITY;
+
+ENTITY IfcConstructionResource
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcConstructionEquipmentResource
+	,IfcConstructionMaterialResource
+	,IfcConstructionProductResource
+	,IfcCrewResource
+	,IfcLaborResource
+	,IfcSubContractResource))
+ SUBTYPE OF (IfcResource);
+	ResourceIdentifier : OPTIONAL IfcIdentifier;
+	ResourceGroup : OPTIONAL IfcLabel;
+	ResourceConsumption : OPTIONAL IfcResourceConsumptionEnum;
+	BaseQuantity : OPTIONAL IfcMeasureWithUnit;
+END_ENTITY;
+
+ENTITY IfcContextDependentUnit
+ SUBTYPE OF (IfcNamedUnit);
+	Name : IfcLabel;
+END_ENTITY;
+
+ENTITY IfcControl
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcActionRequest
+	,IfcConditionCriterion
+	,IfcCostItem
+	,IfcCostSchedule
+	,IfcEquipmentStandard
+	,IfcFurnitureStandard
+	,IfcPerformanceHistory
+	,IfcPermit
+	,IfcProjectOrder
+	,IfcProjectOrderRecord
+	,IfcScheduleTimeControl
+	,IfcServiceLife
+	,IfcSpaceProgram
+	,IfcTimeSeriesSchedule
+	,IfcWorkControl))
+ SUBTYPE OF (IfcObject);
+ INVERSE
+	Controls : SET [0:?] OF IfcRelAssignsToControl FOR RelatingControl;
+END_ENTITY;
+
+ENTITY IfcControllerType
+ SUBTYPE OF (IfcDistributionControlElementType);
+	PredefinedType : IfcControllerTypeEnum;
+END_ENTITY;
+
+ENTITY IfcConversionBasedUnit
+ SUBTYPE OF (IfcNamedUnit);
+	Name : IfcLabel;
+	ConversionFactor : IfcMeasureWithUnit;
+END_ENTITY;
+
+ENTITY IfcCooledBeamType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcCooledBeamTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcCooledBeamTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcCooledBeamTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcCoolingTowerType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcCoolingTowerTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcCoolingTowerTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcCoolingTowerTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcCoordinatedUniversalTimeOffset;
+	HourOffset : IfcHourInDay;
+	MinuteOffset : OPTIONAL IfcMinuteInHour;
+	Sense : IfcAheadOrBehind;
+END_ENTITY;
+
+ENTITY IfcCostItem
+ SUBTYPE OF (IfcControl);
+END_ENTITY;
+
+ENTITY IfcCostSchedule
+ SUBTYPE OF (IfcControl);
+	SubmittedBy : OPTIONAL IfcActorSelect;
+	PreparedBy : OPTIONAL IfcActorSelect;
+	SubmittedOn : OPTIONAL IfcDateTimeSelect;
+	Status : OPTIONAL IfcLabel;
+	TargetUsers : OPTIONAL SET [1:?] OF IfcActorSelect;
+	UpdateDate : OPTIONAL IfcDateTimeSelect;
+	ID : IfcIdentifier;
+	PredefinedType : IfcCostScheduleTypeEnum;
+ UNIQUE
+	UR2 : ID;
+END_ENTITY;
+
+ENTITY IfcCostValue
+ SUBTYPE OF (IfcAppliedValue);
+	CostType : IfcLabel;
+	Condition : OPTIONAL IfcText;
+END_ENTITY;
+
+ENTITY IfcCovering
+ SUBTYPE OF (IfcBuildingElement);
+	PredefinedType : OPTIONAL IfcCoveringTypeEnum;
+ INVERSE
+	CoversSpaces : SET [0:1] OF IfcRelCoversSpaces FOR RelatedCoverings;
+	Covers : SET [0:1] OF IfcRelCoversBldgElements FOR RelatedCoverings;
+END_ENTITY;
+
+ENTITY IfcCoveringType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcCoveringTypeEnum;
+END_ENTITY;
+
+ENTITY IfcCraneRailAShapeProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	OverallHeight : IfcPositiveLengthMeasure;
+	BaseWidth2 : IfcPositiveLengthMeasure;
+	Radius : OPTIONAL IfcPositiveLengthMeasure;
+	HeadWidth : IfcPositiveLengthMeasure;
+	HeadDepth2 : IfcPositiveLengthMeasure;
+	HeadDepth3 : IfcPositiveLengthMeasure;
+	WebThickness : IfcPositiveLengthMeasure;
+	BaseWidth4 : IfcPositiveLengthMeasure;
+	BaseDepth1 : IfcPositiveLengthMeasure;
+	BaseDepth2 : IfcPositiveLengthMeasure;
+	BaseDepth3 : IfcPositiveLengthMeasure;
+	CentreOfGravityInY : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcCraneRailFShapeProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	OverallHeight : IfcPositiveLengthMeasure;
+	HeadWidth : IfcPositiveLengthMeasure;
+	Radius : OPTIONAL IfcPositiveLengthMeasure;
+	HeadDepth2 : IfcPositiveLengthMeasure;
+	HeadDepth3 : IfcPositiveLengthMeasure;
+	WebThickness : IfcPositiveLengthMeasure;
+	BaseDepth1 : IfcPositiveLengthMeasure;
+	BaseDepth2 : IfcPositiveLengthMeasure;
+	CentreOfGravityInY : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcCrewResource
+ SUBTYPE OF (IfcConstructionResource);
+END_ENTITY;
+
+ENTITY IfcCsgPrimitive3D
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBlock
+	,IfcRectangularPyramid
+	,IfcRightCircularCone
+	,IfcRightCircularCylinder
+	,IfcSphere))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Position : IfcAxis2Placement3D;
+ DERIVE
+	Dim : IfcDimensionCount := 3;
+END_ENTITY;
+
+ENTITY IfcCsgSolid
+ SUBTYPE OF (IfcSolidModel);
+	TreeRootExpression : IfcCsgSelect;
+END_ENTITY;
+
+ENTITY IfcCurrencyRelationship;
+	RelatingMonetaryUnit : IfcMonetaryUnit;
+	RelatedMonetaryUnit : IfcMonetaryUnit;
+	ExchangeRate : IfcPositiveRatioMeasure;
+	RateDateTime : IfcDateAndTime;
+	RateSource : OPTIONAL IfcLibraryInformation;
+END_ENTITY;
+
+ENTITY IfcCurtainWall
+ SUBTYPE OF (IfcBuildingElement);
+END_ENTITY;
+
+ENTITY IfcCurtainWallType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcCurtainWallTypeEnum;
+END_ENTITY;
+
+ENTITY IfcCurve
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBoundedCurve
+	,IfcConic
+	,IfcLine
+	,IfcOffsetCurve2D
+	,IfcOffsetCurve3D))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+ DERIVE
+	Dim : IfcDimensionCount := IfcCurveDim(SELF);
+END_ENTITY;
+
+ENTITY IfcCurveBoundedPlane
+ SUBTYPE OF (IfcBoundedSurface);
+	BasisSurface : IfcPlane;
+	OuterBoundary : IfcCurve;
+	InnerBoundaries : SET [0:?] OF IfcCurve;
+ DERIVE
+	Dim : IfcDimensionCount := BasisSurface.Dim;
+END_ENTITY;
+
+ENTITY IfcCurveStyle
+ SUBTYPE OF (IfcPresentationStyle);
+	CurveFont : OPTIONAL IfcCurveFontOrScaledCurveFontSelect;
+	CurveWidth : OPTIONAL IfcSizeSelect;
+	CurveColour : OPTIONAL IfcColour;
+ WHERE
+	WR11 : (NOT(EXISTS(CurveWidth))) OR
+             ('IFC2X3.IFCPOSITIVELENGTHMEASURE' IN TYPEOF(CurveWidth)) OR 
+              (('IFC2X3.IFCDESCRIPTIVEMEASURE' IN TYPEOF(CurveWidth)) AND
+              (CurveWidth = 'by layer'));
+END_ENTITY;
+
+ENTITY IfcCurveStyleFont;
+	Name : OPTIONAL IfcLabel;
+	PatternList : LIST [1:?] OF IfcCurveStyleFontPattern;
+END_ENTITY;
+
+ENTITY IfcCurveStyleFontAndScaling;
+	Name : OPTIONAL IfcLabel;
+	CurveFont : IfcCurveStyleFontSelect;
+	CurveFontScaling : IfcPositiveRatioMeasure;
+END_ENTITY;
+
+ENTITY IfcCurveStyleFontPattern;
+	VisibleSegmentLength : IfcLengthMeasure;
+	InvisibleSegmentLength : IfcPositiveLengthMeasure;
+ WHERE
+	WR01 : VisibleSegmentLength >= 0.;
+END_ENTITY;
+
+ENTITY IfcDamperType
+ SUBTYPE OF (IfcFlowControllerType);
+	PredefinedType : IfcDamperTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcDamperTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcDamperTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcDateAndTime;
+	DateComponent : IfcCalendarDate;
+	TimeComponent : IfcLocalTime;
+END_ENTITY;
+
+ENTITY IfcDefinedSymbol
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Definition : IfcDefinedSymbolSelect;
+	Target : IfcCartesianTransformationOperator2D;
+END_ENTITY;
+
+ENTITY IfcDerivedProfileDef
+ SUBTYPE OF (IfcProfileDef);
+	ParentProfile : IfcProfileDef;
+	Operator : IfcCartesianTransformationOperator2D;
+	Label : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : SELF\IfcProfileDef.ProfileType = ParentProfile.ProfileType;
+END_ENTITY;
+
+ENTITY IfcDerivedUnit;
+	Elements : SET [1:?] OF IfcDerivedUnitElement;
+	UnitType : IfcDerivedUnitEnum;
+	UserDefinedType : OPTIONAL IfcLabel;
+ DERIVE
+	Dimensions : IfcDimensionalExponents := IfcDeriveDimensionalExponents(SELF);
+ WHERE
+	WR1 : (SIZEOF (Elements) > 1) OR ((SIZEOF (Elements) = 1) AND (Elements[1].Exponent <> 1 ));
+	WR2 : (UnitType <> IfcDerivedUnitEnum.USERDEFINED) OR
+            ((UnitType = IfcDerivedUnitEnum.USERDEFINED) AND 
+             (EXISTS(SELF.UserDefinedType)));
+END_ENTITY;
+
+ENTITY IfcDerivedUnitElement;
+	Unit : IfcNamedUnit;
+	Exponent : INTEGER;
+END_ENTITY;
+
+ENTITY IfcDiameterDimension
+ SUBTYPE OF (IfcDimensionCurveDirectedCallout);
+END_ENTITY;
+
+ENTITY IfcDimensionCalloutRelationship
+ SUBTYPE OF (IfcDraughtingCalloutRelationship);
+ WHERE
+	WR11 : SELF\IfcDraughtingCalloutRelationship.Name IN ['primary','secondary'];
+	WR12 : SIZEOF(TYPEOF(SELF\IfcDraughtingCalloutRelationship.RelatingDraughtingCallout) * [
+                  'IFC2X3.IFCANGULARDIMENSION',
+                  'IFC2X3.IFCDIAMETERDIMENSION',
+                  'IFC2X3.IFCLINEARDIMENSION',
+                  'IFC2X3.IFCRADIUSDIMENSION']) = 1;
+	WR13 : NOT ('IFC2X3.IFCDIMENSIONCURVEDIRECTEDCALLOUT'
+               IN TYPEOF (SELF\IfcDraughtingCalloutRelationship.RelatedDraughtingCallout));
+END_ENTITY;
+
+ENTITY IfcDimensionCurve
+ SUBTYPE OF (IfcAnnotationCurveOccurrence);
+ INVERSE
+	AnnotatedBySymbols : SET [0:2] OF IfcTerminatorSymbol FOR AnnotatedCurve;
+ WHERE
+	WR51 : SIZEOF(USEDIN(SELF,'IFC2X3.IFCDRAUGHTINGCALLOUT.CONTENTS')) 
+                   >= 1;
+	WR52 : (SIZEOF(QUERY (Dct1 <* USEDIN(SELF,'IFC2X3.' + 
+                            'IFCTERMINATORSYMBOL.ANNOTATEDCURVE') | (Dct1.Role = IfcDimensionExtentUsage.ORIGIN))) <= 1) 
+             AND 
+             (SIZEOF(QUERY (Dct2 <* USEDIN(SELF,'IFC2X3.' + 
+                            'IFCTERMINATORSYMBOL.ANNOTATEDCURVE') | (Dct2.Role = IfcDimensionExtentUsage.TARGET))) <= 1);
+	WR53 : SIZEOF(QUERY (Dct <* AnnotatedBySymbols | 
+               NOT('IFC2X3.IFCDIMENSIONCURVETERMINATOR' IN TYPEOF(Dct)))) 
+               = 0;
+END_ENTITY;
+
+ENTITY IfcDimensionCurveDirectedCallout
+ SUPERTYPE OF (ONEOF
+	(IfcAngularDimension
+	,IfcDiameterDimension
+	,IfcLinearDimension
+	,IfcRadiusDimension))
+ SUBTYPE OF (IfcDraughtingCallout);
+ WHERE
+	WR41 : SIZEOF(QUERY (Dc <* SELF\IfcDraughtingCallout.Contents | (
+                   'IFC2X3.IFCDIMENSIONCURVE' IN TYPEOF(Dc)))) 
+                  = 1;
+	WR42 : SIZEOF (QUERY (Dc <* SELF.contents |
+                    ('IFC2X3.IFCPROJECTIONCURVE' IN
+                      TYPEOF (Dc)))) <= 2;
+END_ENTITY;
+
+ENTITY IfcDimensionCurveTerminator
+ SUBTYPE OF (IfcTerminatorSymbol);
+	Role : IfcDimensionExtentUsage;
+ WHERE
+	WR61 : 'IFC2X3.IFCDIMENSIONCURVE' IN TYPEOF
+             (SELF\IfcTerminatorSymbol.AnnotatedCurve);
+END_ENTITY;
+
+ENTITY IfcDimensionPair
+ SUBTYPE OF (IfcDraughtingCalloutRelationship);
+ WHERE
+	WR11 : SELF.Name IN ['chained','parallel'];
+	WR12 : SIZEOF(TYPEOF(SELF.RelatingDraughtingCallout) * [
+                            'IFC2X3.IFCANGULARDIMENSION',
+                            'IFC2X3.IFCDIAMETERDIMENSION',
+                            'IFC2X3.IFCLINEARDIMENSION',
+                            'IFC2X3.IFCRADIUSDIMENSION']) = 1;
+	WR13 : SIZEOF(TYPEOF(SELF.RelatedDraughtingCallout) * [
+                            'IFC2X3.IFCANGULARDIMENSION',
+                            'IFC2X3.IFCDIAMETERDIMENSION',
+                            'IFC2X3.IFCLINEARDIMENSION',
+                            'IFC2X3.IFCRADIUSDIMENSION']) = 1;
+END_ENTITY;
+
+ENTITY IfcDimensionalExponents;
+	LengthExponent : INTEGER;
+	MassExponent : INTEGER;
+	TimeExponent : INTEGER;
+	ElectricCurrentExponent : INTEGER;
+	ThermodynamicTemperatureExponent : INTEGER;
+	AmountOfSubstanceExponent : INTEGER;
+	LuminousIntensityExponent : INTEGER;
+END_ENTITY;
+
+ENTITY IfcDirection
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	DirectionRatios : LIST [2:3] OF REAL;
+ DERIVE
+	Dim : IfcDimensionCount := HIINDEX(DirectionRatios);
+END_ENTITY;
+
+ENTITY IfcDiscreteAccessory
+ SUBTYPE OF (IfcElementComponent);
+END_ENTITY;
+
+ENTITY IfcDiscreteAccessoryType
+ SUPERTYPE OF (ONEOF
+	(IfcVibrationIsolatorType))
+ SUBTYPE OF (IfcElementComponentType);
+END_ENTITY;
+
+ENTITY IfcDistributionChamberElement
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcDistributionChamberElementType
+ SUBTYPE OF (IfcDistributionFlowElementType);
+	PredefinedType : IfcDistributionChamberElementTypeEnum;
+END_ENTITY;
+
+ENTITY IfcDistributionControlElement
+ SUBTYPE OF (IfcDistributionElement);
+	ControlElementId : OPTIONAL IfcIdentifier;
+ INVERSE
+	AssignedToFlowElement : SET [0:1] OF IfcRelFlowControlElements FOR RelatedControlElements;
+END_ENTITY;
+
+ENTITY IfcDistributionControlElementType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcActuatorType
+	,IfcAlarmType
+	,IfcControllerType
+	,IfcFlowInstrumentType
+	,IfcSensorType))
+ SUBTYPE OF (IfcDistributionElementType);
+END_ENTITY;
+
+ENTITY IfcDistributionElement
+ SUPERTYPE OF (ONEOF
+	(IfcDistributionControlElement
+	,IfcDistributionFlowElement))
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcDistributionElementType
+ SUPERTYPE OF (ONEOF
+	(IfcDistributionControlElementType
+	,IfcDistributionFlowElementType))
+ SUBTYPE OF (IfcElementType);
+END_ENTITY;
+
+ENTITY IfcDistributionFlowElement
+ SUPERTYPE OF (ONEOF
+	(IfcDistributionChamberElement
+	,IfcEnergyConversionDevice
+	,IfcFlowController
+	,IfcFlowFitting
+	,IfcFlowMovingDevice
+	,IfcFlowSegment
+	,IfcFlowStorageDevice
+	,IfcFlowTerminal
+	,IfcFlowTreatmentDevice))
+ SUBTYPE OF (IfcDistributionElement);
+ INVERSE
+	HasControlElements : SET [0:1] OF IfcRelFlowControlElements FOR RelatingFlowElement;
+END_ENTITY;
+
+ENTITY IfcDistributionFlowElementType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDistributionChamberElementType
+	,IfcEnergyConversionDeviceType
+	,IfcFlowControllerType
+	,IfcFlowFittingType
+	,IfcFlowMovingDeviceType
+	,IfcFlowSegmentType
+	,IfcFlowStorageDeviceType
+	,IfcFlowTerminalType
+	,IfcFlowTreatmentDeviceType))
+ SUBTYPE OF (IfcDistributionElementType);
+END_ENTITY;
+
+ENTITY IfcDistributionPort
+ SUBTYPE OF (IfcPort);
+	FlowDirection : OPTIONAL IfcFlowDirectionEnum;
+END_ENTITY;
+
+ENTITY IfcDocumentElectronicFormat;
+	FileExtension : OPTIONAL IfcLabel;
+	MimeContentType : OPTIONAL IfcLabel;
+	MimeSubtype : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : EXISTS(FileExtension) OR EXISTS(MimeContentType);
+END_ENTITY;
+
+ENTITY IfcDocumentInformation;
+	DocumentId : IfcIdentifier;
+	Name : IfcLabel;
+	Description : OPTIONAL IfcText;
+	DocumentReferences : OPTIONAL SET [1:?] OF IfcDocumentReference;
+	Purpose : OPTIONAL IfcText;
+	IntendedUse : OPTIONAL IfcText;
+	Scope : OPTIONAL IfcText;
+	Revision : OPTIONAL IfcLabel;
+	DocumentOwner : OPTIONAL IfcActorSelect;
+	Editors : OPTIONAL SET [1:?] OF IfcActorSelect;
+	CreationTime : OPTIONAL IfcDateAndTime;
+	LastRevisionTime : OPTIONAL IfcDateAndTime;
+	ElectronicFormat : OPTIONAL IfcDocumentElectronicFormat;
+	ValidFrom : OPTIONAL IfcCalendarDate;
+	ValidUntil : OPTIONAL IfcCalendarDate;
+	Confidentiality : OPTIONAL IfcDocumentConfidentialityEnum;
+	Status : OPTIONAL IfcDocumentStatusEnum;
+ INVERSE
+	IsPointedTo : SET [0:?] OF IfcDocumentInformationRelationship FOR RelatedDocuments;
+	IsPointer : SET [0:1] OF IfcDocumentInformationRelationship FOR RelatingDocument;
+END_ENTITY;
+
+ENTITY IfcDocumentInformationRelationship;
+	RelatingDocument : IfcDocumentInformation;
+	RelatedDocuments : SET [1:?] OF IfcDocumentInformation;
+	RelationshipType : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcDocumentReference
+ SUBTYPE OF (IfcExternalReference);
+ INVERSE
+	ReferenceToDocument : SET [0:1] OF IfcDocumentInformation FOR DocumentReferences;
+ WHERE
+	WR1 : EXISTS(Name) XOR EXISTS(ReferenceToDocument[1]);
+END_ENTITY;
+
+ENTITY IfcDoor
+ SUBTYPE OF (IfcBuildingElement);
+	OverallHeight : OPTIONAL IfcPositiveLengthMeasure;
+	OverallWidth : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcDoorLiningProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	LiningDepth : OPTIONAL IfcPositiveLengthMeasure;
+	LiningThickness : OPTIONAL IfcPositiveLengthMeasure;
+	ThresholdDepth : OPTIONAL IfcPositiveLengthMeasure;
+	ThresholdThickness : OPTIONAL IfcPositiveLengthMeasure;
+	TransomThickness : OPTIONAL IfcPositiveLengthMeasure;
+	TransomOffset : OPTIONAL IfcLengthMeasure;
+	LiningOffset : OPTIONAL IfcLengthMeasure;
+	ThresholdOffset : OPTIONAL IfcLengthMeasure;
+	CasingThickness : OPTIONAL IfcPositiveLengthMeasure;
+	CasingDepth : OPTIONAL IfcPositiveLengthMeasure;
+	ShapeAspectStyle : OPTIONAL IfcShapeAspect;
+ WHERE
+	WR31 : NOT(NOT(EXISTS(LiningDepth)) AND EXISTS(LiningThickness));
+	WR32 : NOT(NOT(EXISTS(ThresholdDepth)) AND EXISTS(ThresholdThickness));
+	WR33 : (EXISTS(TransomOffset) AND EXISTS(TransomThickness)) XOR
+             (NOT(EXISTS(TransomOffset)) AND NOT(EXISTS(TransomThickness)));
+	WR34 : (EXISTS(CasingDepth) AND EXISTS(CasingThickness)) XOR
+             (NOT(EXISTS(CasingDepth)) AND NOT(EXISTS(CasingThickness)));
+	WR35 : EXISTS(SELF\IfcPropertySetDefinition.DefinesType[1]) AND 
+             ('IFC2X3.IFCDOORSTYLE' IN TYPEOF(SELF\IfcPropertySetDefinition.DefinesType[1]));
+END_ENTITY;
+
+ENTITY IfcDoorPanelProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	PanelDepth : OPTIONAL IfcPositiveLengthMeasure;
+	PanelOperation : IfcDoorPanelOperationEnum;
+	PanelWidth : OPTIONAL IfcNormalisedRatioMeasure;
+	PanelPosition : IfcDoorPanelPositionEnum;
+	ShapeAspectStyle : OPTIONAL IfcShapeAspect;
+ WHERE
+	WR31 : EXISTS(SELF\IfcPropertySetDefinition.DefinesType[1]) AND 
+             ('IFC2X3.IFCDOORSTYLE' IN TYPEOF(SELF\IfcPropertySetDefinition.DefinesType[1]));
+END_ENTITY;
+
+ENTITY IfcDoorStyle
+ SUBTYPE OF (IfcTypeProduct);
+	OperationType : IfcDoorStyleOperationEnum;
+	ConstructionType : IfcDoorStyleConstructionEnum;
+	ParameterTakesPrecedence : BOOLEAN;
+	Sizeable : BOOLEAN;
+END_ENTITY;
+
+ENTITY IfcDraughtingCallout
+ SUPERTYPE OF (ONEOF
+	(IfcDimensionCurveDirectedCallout
+	,IfcStructuredDimensionCallout))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Contents : SET [1:?] OF IfcDraughtingCalloutElement;
+ INVERSE
+	IsRelatedFromCallout : SET [0:?] OF IfcDraughtingCalloutRelationship FOR RelatedDraughtingCallout;
+	IsRelatedToCallout : SET [0:?] OF IfcDraughtingCalloutRelationship FOR RelatingDraughtingCallout;
+END_ENTITY;
+
+ENTITY IfcDraughtingCalloutRelationship
+ SUPERTYPE OF (ONEOF
+	(IfcDimensionCalloutRelationship
+	,IfcDimensionPair));
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+	RelatingDraughtingCallout : IfcDraughtingCallout;
+	RelatedDraughtingCallout : IfcDraughtingCallout;
+END_ENTITY;
+
+ENTITY IfcDraughtingPreDefinedColour
+ SUBTYPE OF (IfcPreDefinedColour);
+ WHERE
+	WR31 : SELF\IfcPreDefinedItem.Name IN ['black','red','green','blue','yellow',
+                  'magenta','cyan','white','by layer'];
+END_ENTITY;
+
+ENTITY IfcDraughtingPreDefinedCurveFont
+ SUBTYPE OF (IfcPreDefinedCurveFont);
+ WHERE
+	WR31 : SELF\IfcPredefinedItem.Name IN
+                    ['continuous',
+                     'chain',
+                     'chain double dash',
+                     'dashed',
+                     'dotted',
+                     'by layer'];
+END_ENTITY;
+
+ENTITY IfcDraughtingPreDefinedTextFont
+ SUBTYPE OF (IfcPreDefinedTextFont);
+ WHERE
+	WR31 : SELF\IfcPreDefinedItem.Name IN ['ISO 3098-1 font A','ISO 3098-1 font B'];
+END_ENTITY;
+
+ENTITY IfcDuctFittingType
+ SUBTYPE OF (IfcFlowFittingType);
+	PredefinedType : IfcDuctFittingTypeEnum;
+ WHERE
+	WR2 : (PredefinedType <> IfcDuctFittingTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcDuctFittingTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcDuctSegmentType
+ SUBTYPE OF (IfcFlowSegmentType);
+	PredefinedType : IfcDuctSegmentTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcDuctSegmentTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcDuctSegmentTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcDuctSilencerType
+ SUBTYPE OF (IfcFlowTreatmentDeviceType);
+	PredefinedType : IfcDuctSilencerTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcDuctSilencerTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcDuctSilencerTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcEdge
+ SUPERTYPE OF (ONEOF
+	(IfcEdgeCurve
+	,IfcOrientedEdge
+	,IfcSubedge))
+ SUBTYPE OF (IfcTopologicalRepresentationItem);
+	EdgeStart : IfcVertex;
+	EdgeEnd : IfcVertex;
+END_ENTITY;
+
+ENTITY IfcEdgeCurve
+ SUBTYPE OF (IfcEdge);
+	EdgeGeometry : IfcCurve;
+	SameSense : BOOLEAN;
+END_ENTITY;
+
+ENTITY IfcEdgeFeature
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcChamferEdgeFeature
+	,IfcRoundedEdgeFeature))
+ SUBTYPE OF (IfcFeatureElementSubtraction);
+	FeatureLength : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcEdgeLoop
+ SUBTYPE OF (IfcLoop);
+	EdgeList : LIST [1:?] OF IfcOrientedEdge;
+ DERIVE
+	Ne : INTEGER := SIZEOF(EdgeList);
+ WHERE
+	WR1 : (EdgeList[1].EdgeStart) :=: (EdgeList[Ne].EdgeEnd);
+	WR2 : IfcLoopHeadToTail(SELF);
+END_ENTITY;
+
+ENTITY IfcElectricApplianceType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcElectricApplianceTypeEnum;
+END_ENTITY;
+
+ENTITY IfcElectricDistributionPoint
+ SUBTYPE OF (IfcFlowController);
+	DistributionPointFunction : IfcElectricDistributionPointFunctionEnum;
+	UserDefinedFunction : OPTIONAL IfcLabel;
+ WHERE
+	WR31 : (DistributionPointFunction <> IfcElectricDistributionPointFunctionEnum.USERDEFINED) OR
+             ((DistributionPointFunction = IfcElectricDistributionPointFunctionEnum.USERDEFINED) AND EXISTS(SELF\IfcElectricDistributionPoint.UserDefinedFunction));
+END_ENTITY;
+
+ENTITY IfcElectricFlowStorageDeviceType
+ SUBTYPE OF (IfcFlowStorageDeviceType);
+	PredefinedType : IfcElectricFlowStorageDeviceTypeEnum;
+END_ENTITY;
+
+ENTITY IfcElectricGeneratorType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcElectricGeneratorTypeEnum;
+END_ENTITY;
+
+ENTITY IfcElectricHeaterType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcElectricHeaterTypeEnum;
+END_ENTITY;
+
+ENTITY IfcElectricMotorType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcElectricMotorTypeEnum;
+END_ENTITY;
+
+ENTITY IfcElectricTimeControlType
+ SUBTYPE OF (IfcFlowControllerType);
+	PredefinedType : IfcElectricTimeControlTypeEnum;
+END_ENTITY;
+
+ENTITY IfcElectricalBaseProperties
+ SUBTYPE OF (IfcEnergyProperties);
+	ElectricCurrentType : OPTIONAL IfcElectricCurrentEnum;
+	InputVoltage : IfcElectricVoltageMeasure;
+	InputFrequency : IfcFrequencyMeasure;
+	FullLoadCurrent : OPTIONAL IfcElectricCurrentMeasure;
+	MinimumCircuitCurrent : OPTIONAL IfcElectricCurrentMeasure;
+	MaximumPowerInput : OPTIONAL IfcPowerMeasure;
+	RatedPowerInput : OPTIONAL IfcPowerMeasure;
+	InputPhase : INTEGER;
+END_ENTITY;
+
+ENTITY IfcElectricalCircuit
+ SUBTYPE OF (IfcSystem);
+END_ENTITY;
+
+ENTITY IfcElectricalElement
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcElement
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBuildingElement
+	,IfcDistributionElement
+	,IfcElectricalElement
+	,IfcElementAssembly
+	,IfcElementComponent
+	,IfcEquipmentElement
+	,IfcFeatureElement
+	,IfcFurnishingElement
+	,IfcTransportElement
+	,IfcVirtualElement))
+ SUBTYPE OF (IfcProduct);
+	Tag : OPTIONAL IfcIdentifier;
+ INVERSE
+	FillsVoids : SET [0:1] OF IfcRelFillsElement FOR RelatedBuildingElement;
+	ConnectedTo : SET [0:?] OF IfcRelConnectsElements FOR RelatingElement;
+	HasCoverings : SET [0:?] OF IfcRelCoversBldgElements FOR RelatingBuildingElement;
+	HasProjections : SET [0:?] OF IfcRelProjectsElement FOR RelatingElement;
+	HasStructuralMember : SET [0:?] OF IfcRelConnectsStructuralElement FOR RelatingElement;
+	ReferencedInStructures : SET [0:?] OF IfcRelReferencedInSpatialStructure FOR RelatedElements;
+	HasPorts : SET [0:?] OF IfcRelConnectsPortToElement FOR RelatedElement;
+	HasOpenings : SET [0:?] OF IfcRelVoidsElement FOR RelatingBuildingElement;
+	IsConnectionRealization : SET [0:?] OF IfcRelConnectsWithRealizingElements FOR RealizingElements;
+	ProvidesBoundaries : SET [0:?] OF IfcRelSpaceBoundary FOR RelatedBuildingElement;
+	ConnectedFrom : SET [0:?] OF IfcRelConnectsElements FOR RelatedElement;
+	ContainedInStructure : SET [0:1] OF IfcRelContainedInSpatialStructure FOR RelatedElements;
+END_ENTITY;
+
+ENTITY IfcElementAssembly
+ SUBTYPE OF (IfcElement);
+	AssemblyPlace : OPTIONAL IfcAssemblyPlaceEnum;
+	PredefinedType : IfcElementAssemblyTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcElementAssemblyTypeEnum.USERDEFINED) OR ((PredefinedType = IfcElementAssemblyTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcObject.ObjectType));
+END_ENTITY;
+
+ENTITY IfcElementComponent
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDiscreteAccessory
+	,IfcFastener))
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcElementComponentType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDiscreteAccessoryType
+	,IfcFastenerType))
+ SUBTYPE OF (IfcElementType);
+END_ENTITY;
+
+ENTITY IfcElementQuantity
+ SUBTYPE OF (IfcPropertySetDefinition);
+	MethodOfMeasurement : OPTIONAL IfcLabel;
+	Quantities : SET [1:?] OF IfcPhysicalQuantity;
+END_ENTITY;
+
+ENTITY IfcElementType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBuildingElementType
+	,IfcDistributionElementType
+	,IfcElementComponentType
+	,IfcFurnishingElementType
+	,IfcSpatialStructureElementType
+	,IfcTransportElementType))
+ SUBTYPE OF (IfcTypeProduct);
+	ElementType : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcElementarySurface
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcPlane))
+ SUBTYPE OF (IfcSurface);
+	Position : IfcAxis2Placement3D;
+ DERIVE
+	Dim : IfcDimensionCount := Position.Dim;
+END_ENTITY;
+
+ENTITY IfcEllipse
+ SUBTYPE OF (IfcConic);
+	SemiAxis1 : IfcPositiveLengthMeasure;
+	SemiAxis2 : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcEllipseProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	SemiAxis1 : IfcPositiveLengthMeasure;
+	SemiAxis2 : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcEnergyConversionDevice
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcEnergyConversionDeviceType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcAirToAirHeatRecoveryType
+	,IfcBoilerType
+	,IfcChillerType
+	,IfcCoilType
+	,IfcCondenserType
+	,IfcCooledBeamType
+	,IfcCoolingTowerType
+	,IfcElectricGeneratorType
+	,IfcElectricMotorType
+	,IfcEvaporativeCoolerType
+	,IfcEvaporatorType
+	,IfcHeatExchangerType
+	,IfcHumidifierType
+	,IfcMotorConnectionType
+	,IfcSpaceHeaterType
+	,IfcTransformerType
+	,IfcTubeBundleType
+	,IfcUnitaryEquipmentType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcEnergyProperties
+ SUPERTYPE OF (ONEOF
+	(IfcElectricalBaseProperties))
+ SUBTYPE OF (IfcPropertySetDefinition);
+	EnergySequence : OPTIONAL IfcEnergySequenceEnum;
+	UserDefinedEnergySequence : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcEnvironmentalImpactValue
+ SUBTYPE OF (IfcAppliedValue);
+	ImpactType : IfcLabel;
+	Category : IfcEnvironmentalImpactCategoryEnum;
+	UserDefinedCategory : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : (Category <> IfcEnvironmentalImpactCategoryEnum.USERDEFINED) OR
+            ((Category = IfcEnvironmentalImpactCategoryEnum.USERDEFINED) AND EXISTS(SELF\IfcEnvironmentalImpactValue.UserDefinedCategory));
+END_ENTITY;
+
+ENTITY IfcEquipmentElement
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcEquipmentStandard
+ SUBTYPE OF (IfcControl);
+END_ENTITY;
+
+ENTITY IfcEvaporativeCoolerType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcEvaporativeCoolerTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcEvaporativeCoolerTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcEvaporativeCoolerTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcEvaporatorType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcEvaporatorTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcEvaporatorTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcEvaporatorTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcExtendedMaterialProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	ExtendedProperties : SET [1:?] OF IfcProperty;
+	Description : OPTIONAL IfcText;
+	Name : IfcLabel;
+END_ENTITY;
+
+ENTITY IfcExternalReference
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcClassificationReference
+	,IfcDocumentReference
+	,IfcExternallyDefinedHatchStyle
+	,IfcExternallyDefinedSurfaceStyle
+	,IfcExternallyDefinedSymbol
+	,IfcExternallyDefinedTextFont
+	,IfcLibraryReference));
+	Location : OPTIONAL IfcLabel;
+	ItemReference : OPTIONAL IfcIdentifier;
+	Name : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : EXISTS(ItemReference) OR EXISTS(Location) OR EXISTS(Name);
+END_ENTITY;
+
+ENTITY IfcExternallyDefinedHatchStyle
+ SUBTYPE OF (IfcExternalReference);
+END_ENTITY;
+
+ENTITY IfcExternallyDefinedSurfaceStyle
+ SUBTYPE OF (IfcExternalReference);
+END_ENTITY;
+
+ENTITY IfcExternallyDefinedSymbol
+ SUBTYPE OF (IfcExternalReference);
+END_ENTITY;
+
+ENTITY IfcExternallyDefinedTextFont
+ SUBTYPE OF (IfcExternalReference);
+END_ENTITY;
+
+ENTITY IfcExtrudedAreaSolid
+ SUBTYPE OF (IfcSweptAreaSolid);
+	ExtrudedDirection : IfcDirection;
+	Depth : IfcPositiveLengthMeasure;
+ WHERE
+	WR31 : IfcDotProduct(IfcRepresentationItem() || IfcGeometricRepresentationItem() || IfcDirection([0.0,0.0,1.0]), SELF.ExtrudedDirection) <> 0.0;
+END_ENTITY;
+
+ENTITY IfcFace
+ SUPERTYPE OF (ONEOF
+	(IfcFaceSurface))
+ SUBTYPE OF (IfcTopologicalRepresentationItem);
+	Bounds : SET [1:?] OF IfcFaceBound;
+ WHERE
+	WR1 : SIZEOF(QUERY(temp <* Bounds | 'IFC2X3.IFCFACEOUTERBOUND' IN TYPEOF(temp))) <= 1;
+END_ENTITY;
+
+ENTITY IfcFaceBasedSurfaceModel
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	FbsmFaces : SET [1:?] OF IfcConnectedFaceSet;
+ DERIVE
+	Dim : IfcDimensionCount := 3;
+END_ENTITY;
+
+ENTITY IfcFaceBound
+ SUPERTYPE OF (ONEOF
+	(IfcFaceOuterBound))
+ SUBTYPE OF (IfcTopologicalRepresentationItem);
+	Bound : IfcLoop;
+	Orientation : BOOLEAN;
+END_ENTITY;
+
+ENTITY IfcFaceOuterBound
+ SUBTYPE OF (IfcFaceBound);
+END_ENTITY;
+
+ENTITY IfcFaceSurface
+ SUBTYPE OF (IfcFace);
+	FaceSurface : IfcSurface;
+	SameSense : BOOLEAN;
+END_ENTITY;
+
+ENTITY IfcFacetedBrep
+ SUBTYPE OF (IfcManifoldSolidBrep);
+END_ENTITY;
+
+ENTITY IfcFacetedBrepWithVoids
+ SUBTYPE OF (IfcManifoldSolidBrep);
+	Voids : SET [1:?] OF IfcClosedShell;
+END_ENTITY;
+
+ENTITY IfcFailureConnectionCondition
+ SUBTYPE OF (IfcStructuralConnectionCondition);
+	TensionFailureX : OPTIONAL IfcForceMeasure;
+	TensionFailureY : OPTIONAL IfcForceMeasure;
+	TensionFailureZ : OPTIONAL IfcForceMeasure;
+	CompressionFailureX : OPTIONAL IfcForceMeasure;
+	CompressionFailureY : OPTIONAL IfcForceMeasure;
+	CompressionFailureZ : OPTIONAL IfcForceMeasure;
+END_ENTITY;
+
+ENTITY IfcFanType
+ SUBTYPE OF (IfcFlowMovingDeviceType);
+	PredefinedType : IfcFanTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcFanTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcFanTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcFastener
+ SUPERTYPE OF (ONEOF
+	(IfcMechanicalFastener))
+ SUBTYPE OF (IfcElementComponent);
+END_ENTITY;
+
+ENTITY IfcFastenerType
+ SUPERTYPE OF (ONEOF
+	(IfcMechanicalFastenerType))
+ SUBTYPE OF (IfcElementComponentType);
+END_ENTITY;
+
+ENTITY IfcFeatureElement
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcFeatureElementAddition
+	,IfcFeatureElementSubtraction))
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcFeatureElementAddition
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcProjectionElement))
+ SUBTYPE OF (IfcFeatureElement);
+ INVERSE
+	ProjectsElements : IfcRelProjectsElement FOR RelatedFeatureElement;
+END_ENTITY;
+
+ENTITY IfcFeatureElementSubtraction
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcEdgeFeature
+	,IfcOpeningElement))
+ SUBTYPE OF (IfcFeatureElement);
+ INVERSE
+	VoidsElements : IfcRelVoidsElement FOR RelatedOpeningElement;
+END_ENTITY;
+
+ENTITY IfcFillAreaStyle
+ SUBTYPE OF (IfcPresentationStyle);
+	FillStyles : SET [1:?] OF IfcFillStyleSelect;
+ WHERE
+	WR11 : SIZEOF(QUERY(Style <* SELF.FillStyles |
+               'IFC2X3.IFCCOLOUR' IN
+                TYPEOF(Style)
+               )) <= 1;
+	WR12 : SIZEOF(QUERY(Style <* SELF.FillStyles |
+               'IFC2X3.IFCEXTERNALLYDEFINEDHATCHSTYLE' IN
+                TYPEOF(Style)
+               )) <= 1;
+	WR13 : (SIZEOF(QUERY(Style <* SELF.FillStyles |
+               'IFC2X3.IFCEXTERNALLYDEFINEDHATCHSTYLE' IN
+                TYPEOF(Style)
+               )) >= 1)
+             XOR
+             (SIZEOF(QUERY(Style <* SELF.FillStyles |
+               'IFC2X3.IFCFILLAREASTYLEHATCHING' IN
+                TYPEOF(Style)
+               )) >= 1)
+             XOR
+             (SIZEOF(QUERY(Style <* SELF.FillStyles |
+               'IFC2X3.IFCFILLAREASTYLETILES' IN
+                TYPEOF(Style)
+               )) >= 1);
+END_ENTITY;
+
+ENTITY IfcFillAreaStyleHatching
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	HatchLineAppearance : IfcCurveStyle;
+	StartOfNextHatchLine : IfcHatchLineDistanceSelect;
+	PointOfReferenceHatchLine : OPTIONAL IfcCartesianPoint;
+	PatternStart : OPTIONAL IfcCartesianPoint;
+	HatchLineAngle : IfcPlaneAngleMeasure;
+ WHERE
+	WR21 : NOT(
+              'IFC2X3.IFCTWODIRECTIONREPEATFACTOR' 
+              IN TYPEOF(StartOfNextHatchLine)
+             );
+	WR22 : NOT(EXISTS(PatternStart)) 
+             OR (PatternStart.Dim = 2);
+	WR23 : NOT(EXISTS(PointOfReferenceHatchLine)) 
+             OR (PointOfReferenceHatchLine.Dim = 2);
+END_ENTITY;
+
+ENTITY IfcFillAreaStyleTileSymbolWithStyle
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Symbol : IfcAnnotationSymbolOccurrence;
+END_ENTITY;
+
+ENTITY IfcFillAreaStyleTiles
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	TilingPattern : IfcOneDirectionRepeatFactor;
+	Tiles : SET [1:?] OF IfcFillAreaStyleTileShapeSelect;
+	TilingScale : IfcPositiveRatioMeasure;
+END_ENTITY;
+
+ENTITY IfcFilterType
+ SUBTYPE OF (IfcFlowTreatmentDeviceType);
+	PredefinedType : IfcFilterTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcFilterTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcFilterTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcFireSuppressionTerminalType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcFireSuppressionTerminalTypeEnum;
+END_ENTITY;
+
+ENTITY IfcFlowController
+ SUPERTYPE OF (ONEOF
+	(IfcElectricDistributionPoint))
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcFlowControllerType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcAirTerminalBoxType
+	,IfcDamperType
+	,IfcElectricTimeControlType
+	,IfcFlowMeterType
+	,IfcProtectiveDeviceType
+	,IfcSwitchingDeviceType
+	,IfcValveType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcFlowFitting
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcFlowFittingType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCableCarrierFittingType
+	,IfcDuctFittingType
+	,IfcJunctionBoxType
+	,IfcPipeFittingType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcFlowInstrumentType
+ SUBTYPE OF (IfcDistributionControlElementType);
+	PredefinedType : IfcFlowInstrumentTypeEnum;
+END_ENTITY;
+
+ENTITY IfcFlowMeterType
+ SUBTYPE OF (IfcFlowControllerType);
+	PredefinedType : IfcFlowMeterTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcFlowMeterTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcFlowMeterTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcFlowMovingDevice
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcFlowMovingDeviceType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCompressorType
+	,IfcFanType
+	,IfcPumpType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcFlowSegment
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcFlowSegmentType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCableCarrierSegmentType
+	,IfcCableSegmentType
+	,IfcDuctSegmentType
+	,IfcPipeSegmentType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcFlowStorageDevice
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcFlowStorageDeviceType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcElectricFlowStorageDeviceType
+	,IfcTankType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcFlowTerminal
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcFlowTerminalType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcAirTerminalType
+	,IfcElectricApplianceType
+	,IfcElectricHeaterType
+	,IfcFireSuppressionTerminalType
+	,IfcGasTerminalType
+	,IfcLampType
+	,IfcLightFixtureType
+	,IfcOutletType
+	,IfcSanitaryTerminalType
+	,IfcStackTerminalType
+	,IfcWasteTerminalType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcFlowTreatmentDevice
+ SUBTYPE OF (IfcDistributionFlowElement);
+END_ENTITY;
+
+ENTITY IfcFlowTreatmentDeviceType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDuctSilencerType
+	,IfcFilterType))
+ SUBTYPE OF (IfcDistributionFlowElementType);
+END_ENTITY;
+
+ENTITY IfcFluidFlowProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	PropertySource : IfcPropertySourceEnum;
+	FlowConditionTimeSeries : OPTIONAL IfcTimeSeries;
+	VelocityTimeSeries : OPTIONAL IfcTimeSeries;
+	FlowrateTimeSeries : OPTIONAL IfcTimeSeries;
+	Fluid : IfcMaterial;
+	PressureTimeSeries : OPTIONAL IfcTimeSeries;
+	UserDefinedPropertySource : OPTIONAL IfcLabel;
+	TemperatureSingleValue : OPTIONAL IfcThermodynamicTemperatureMeasure;
+	WetBulbTemperatureSingleValue : OPTIONAL IfcThermodynamicTemperatureMeasure;
+	WetBulbTemperatureTimeSeries : OPTIONAL IfcTimeSeries;
+	TemperatureTimeSeries : OPTIONAL IfcTimeSeries;
+	FlowrateSingleValue : OPTIONAL IfcDerivedMeasureValue;
+	FlowConditionSingleValue : OPTIONAL IfcPositiveRatioMeasure;
+	VelocitySingleValue : OPTIONAL IfcLinearVelocityMeasure;
+	PressureSingleValue : OPTIONAL IfcPressureMeasure;
+END_ENTITY;
+
+ENTITY IfcFooting
+ SUBTYPE OF (IfcBuildingElement);
+	PredefinedType : IfcFootingTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcFootingTypeEnum.USERDEFINED) OR ((PredefinedType = IfcFootingTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcObject.ObjectType));
+END_ENTITY;
+
+ENTITY IfcFuelProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	CombustionTemperature : OPTIONAL IfcThermodynamicTemperatureMeasure;
+	CarbonContent : OPTIONAL IfcPositiveRatioMeasure;
+	LowerHeatingValue : OPTIONAL IfcHeatingValueMeasure;
+	HigherHeatingValue : OPTIONAL IfcHeatingValueMeasure;
+ UNIQUE
+	UR11 : Material;
+END_ENTITY;
+
+ENTITY IfcFurnishingElement
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcFurnishingElementType
+ SUPERTYPE OF (ONEOF
+	(IfcFurnitureType
+	,IfcSystemFurnitureElementType))
+ SUBTYPE OF (IfcElementType);
+END_ENTITY;
+
+ENTITY IfcFurnitureStandard
+ SUBTYPE OF (IfcControl);
+END_ENTITY;
+
+ENTITY IfcFurnitureType
+ SUBTYPE OF (IfcFurnishingElementType);
+	AssemblyPlace : IfcAssemblyPlaceEnum;
+END_ENTITY;
+
+ENTITY IfcGasTerminalType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcGasTerminalTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcGasTerminalTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcGasTerminalTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcGeneralMaterialProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	MolecularWeight : OPTIONAL IfcMolecularWeightMeasure;
+	Porosity : OPTIONAL IfcNormalisedRatioMeasure;
+	MassDensity : OPTIONAL IfcMassDensityMeasure;
+ UNIQUE
+	UR11 : Material;
+END_ENTITY;
+
+ENTITY IfcGeneralProfileProperties
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralProfileProperties))
+ SUBTYPE OF (IfcProfileProperties);
+	PhysicalWeight : OPTIONAL IfcMassPerLengthMeasure;
+	Perimeter : OPTIONAL IfcPositiveLengthMeasure;
+	MinimumPlateThickness : OPTIONAL IfcPositiveLengthMeasure;
+	MaximumPlateThickness : OPTIONAL IfcPositiveLengthMeasure;
+	CrossSectionArea : OPTIONAL IfcAreaMeasure;
+ WHERE
+	WR1 : NOT(EXISTS(CrossSectionArea)) OR (CrossSectionArea > 0.);
+END_ENTITY;
+
+ENTITY IfcGeometricCurveSet
+ SUBTYPE OF (IfcGeometricSet);
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcGeometricSet.Elements |
+            'IFC2X3.IFCSURFACE' IN TYPEOF(Temp))) = 0;
+END_ENTITY;
+
+ENTITY IfcGeometricRepresentationContext
+ SUPERTYPE OF (ONEOF
+	(IfcGeometricRepresentationSubContext))
+ SUBTYPE OF (IfcRepresentationContext);
+	CoordinateSpaceDimension : IfcDimensionCount;
+	Precision : OPTIONAL REAL;
+	WorldCoordinateSystem : IfcAxis2Placement;
+	TrueNorth : OPTIONAL IfcDirection;
+ INVERSE
+	HasSubContexts : SET [0:?] OF IfcGeometricRepresentationSubContext FOR ParentContext;
+END_ENTITY;
+
+ENTITY IfcGeometricRepresentationItem
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcAnnotationFillArea
+	,IfcAnnotationSurface
+	,IfcBooleanResult
+	,IfcBoundingBox
+	,IfcCartesianTransformationOperator
+	,IfcCompositeCurveSegment
+	,IfcCsgPrimitive3D
+	,IfcCurve
+	,IfcDefinedSymbol
+	,IfcDirection
+	,IfcDraughtingCallout
+	,IfcFaceBasedSurfaceModel
+	,IfcFillAreaStyleHatching
+	,IfcFillAreaStyleTileSymbolWithStyle
+	,IfcFillAreaStyleTiles
+	,IfcGeometricSet
+	,IfcHalfSpaceSolid
+	,IfcLightSource
+	,IfcOneDirectionRepeatFactor
+	,IfcPlacement
+	,IfcPlanarExtent
+	,IfcPoint
+	,IfcSectionedSpine
+	,IfcShellBasedSurfaceModel
+	,IfcSolidModel
+	,IfcSurface
+	,IfcTextLiteral
+	,IfcVector))
+ SUBTYPE OF (IfcRepresentationItem);
+END_ENTITY;
+
+ENTITY IfcGeometricRepresentationSubContext
+ SUBTYPE OF (IfcGeometricRepresentationContext);
+	ParentContext : IfcGeometricRepresentationContext;
+	TargetScale : OPTIONAL IfcPositiveRatioMeasure;
+	TargetView : IfcGeometricProjectionEnum;
+	UserDefinedTargetView : OPTIONAL IfcLabel;
+ DERIVE
+	SELF\IfcGeometricRepresentationContext.WorldCoordinateSystem : IfcAxis2Placement := ParentContext.WorldCoordinateSystem;
+	SELF\IfcGeometricRepresentationContext.CoordinateSpaceDimension : IfcDimensionCount := ParentContext.CoordinateSpaceDimension;
+	SELF\IfcGeometricRepresentationContext.TrueNorth : IfcDirection := NVL(ParentContext.TrueNorth,SELF.WorldCoordinateSystem.P[2]);
+	SELF\IfcGeometricRepresentationContext.Precision : REAL := NVL(ParentContext.Precision,1.E-5);
+ WHERE
+	WR31 : NOT('IFC2X3.IFCGEOMETRICREPRESENTATIONSUBCONTEXT' IN TYPEOF(ParentContext));
+	WR32 : (TargetView <> IfcGeometricProjectionEnum.USERDEFINED) OR 
+             ((TargetView =  IfcGeometricProjectionEnum.USERDEFINED) AND 
+              EXISTS(UserDefinedTargetView));
+END_ENTITY;
+
+ENTITY IfcGeometricSet
+ SUPERTYPE OF (ONEOF
+	(IfcGeometricCurveSet))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Elements : SET [1:?] OF IfcGeometricSetSelect;
+ DERIVE
+	Dim : IfcDimensionCount := Elements[1].Dim;
+ WHERE
+	WR21 : SIZEOF(QUERY(Temp <* Elements |
+               Temp.Dim <> Elements[1].Dim))
+             = 0;
+END_ENTITY;
+
+ENTITY IfcGrid
+ SUBTYPE OF (IfcProduct);
+	UAxes : LIST [1:?] OF UNIQUE IfcGridAxis;
+	VAxes : LIST [1:?] OF UNIQUE IfcGridAxis;
+	WAxes : OPTIONAL LIST [1:?] OF UNIQUE IfcGridAxis;
+ INVERSE
+	ContainedInStructure : SET [0:1] OF IfcRelContainedInSpatialStructure FOR RelatedElements;
+ WHERE
+	WR41 : EXISTS(SELF\IfcProduct.ObjectPlacement);
+END_ENTITY;
+
+ENTITY IfcGridAxis;
+	AxisTag : OPTIONAL IfcLabel;
+	AxisCurve : IfcCurve;
+	SameSense : IfcBoolean;
+ INVERSE
+	PartOfW : SET [0:1] OF IfcGrid FOR WAxes;
+	PartOfV : SET [0:1] OF IfcGrid FOR VAxes;
+	PartOfU : SET [0:1] OF IfcGrid FOR UAxes;
+	HasIntersections : SET [0:?] OF IfcVirtualGridIntersection FOR IntersectingAxes;
+ WHERE
+	WR1 : AxisCurve.Dim = 2;
+	WR2 : (SIZEOF(PartOfU) = 1) XOR (SIZEOF(PartOfV) = 1) XOR (SIZEOF(PartOfW) = 1);
+END_ENTITY;
+
+ENTITY IfcGridPlacement
+ SUBTYPE OF (IfcObjectPlacement);
+	PlacementLocation : IfcVirtualGridIntersection;
+	PlacementRefDirection : OPTIONAL IfcVirtualGridIntersection;
+END_ENTITY;
+
+ENTITY IfcGroup
+ SUPERTYPE OF (ONEOF
+	(IfcAsset
+	,IfcCondition
+	,IfcInventory
+	,IfcStructuralLoadGroup
+	,IfcStructuralResultGroup
+	,IfcSystem
+	,IfcZone))
+ SUBTYPE OF (IfcObject);
+ INVERSE
+	IsGroupedBy : IfcRelAssignsToGroup FOR RelatingGroup;
+END_ENTITY;
+
+ENTITY IfcHalfSpaceSolid
+ SUPERTYPE OF (ONEOF
+	(IfcBoxedHalfSpace
+	,IfcPolygonalBoundedHalfSpace))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	BaseSurface : IfcSurface;
+	AgreementFlag : BOOLEAN;
+ DERIVE
+	Dim : IfcDimensionCount := 3;
+END_ENTITY;
+
+ENTITY IfcHeatExchangerType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcHeatExchangerTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcHeatExchangerTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcHeatExchangerTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcHumidifierType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcHumidifierTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcHumidifierTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcHumidifierTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcHygroscopicMaterialProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	UpperVaporResistanceFactor : OPTIONAL IfcPositiveRatioMeasure;
+	LowerVaporResistanceFactor : OPTIONAL IfcPositiveRatioMeasure;
+	IsothermalMoistureCapacity : OPTIONAL IfcIsothermalMoistureCapacityMeasure;
+	VaporPermeability : OPTIONAL IfcVaporPermeabilityMeasure;
+	MoistureDiffusivity : OPTIONAL IfcMoistureDiffusivityMeasure;
+ UNIQUE
+	UR11 : Material;
+END_ENTITY;
+
+ENTITY IfcIShapeProfileDef
+ SUPERTYPE OF (ONEOF
+	(IfcAsymmetricIShapeProfileDef))
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	OverallWidth : IfcPositiveLengthMeasure;
+	OverallDepth : IfcPositiveLengthMeasure;
+	WebThickness : IfcPositiveLengthMeasure;
+	FlangeThickness : IfcPositiveLengthMeasure;
+	FilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR1 : FlangeThickness < (OverallDepth / 2.);
+	WR2 : WebThickness < OverallWidth;
+	WR3 : NOT(EXISTS(FilletRadius)) OR
+            ((FilletRadius <= (OverallWidth - WebThickness)/2.) AND 
+             (FilletRadius <= (OverallDepth - (2. * FlangeThickness))/2.));
+END_ENTITY;
+
+ENTITY IfcImageTexture
+ SUBTYPE OF (IfcSurfaceTexture);
+	UrlReference : IfcIdentifier;
+END_ENTITY;
+
+ENTITY IfcInventory
+ SUBTYPE OF (IfcGroup);
+	InventoryType : IfcInventoryTypeEnum;
+	Jurisdiction : IfcActorSelect;
+	ResponsiblePersons : SET [1:?] OF IfcPerson;
+	LastUpdateDate : IfcCalendarDate;
+	CurrentValue : OPTIONAL IfcCostValue;
+	OriginalValue : OPTIONAL IfcCostValue;
+ WHERE
+	WR41 : SIZEOF(QUERY(temp <* SELF\IfcGroup.IsGroupedBy.RelatedObjects |
+                 NOT( ('IFC2X3.IFCSPACE' IN TYPEOF (temp)) OR 
+                      ('IFC2X3.IFCASSET' IN TYPEOF (temp)) OR
+                      ('IFC2X3.IFCFURNISHINGELEMENT' IN TYPEOF (temp))
+                 ))) = 0;
+END_ENTITY;
+
+ENTITY IfcIrregularTimeSeries
+ SUBTYPE OF (IfcTimeSeries);
+	Values : LIST [1:?] OF IfcIrregularTimeSeriesValue;
+END_ENTITY;
+
+ENTITY IfcIrregularTimeSeriesValue;
+	TimeStamp : IfcDateTimeSelect;
+	ListValues : LIST [1:?] OF IfcValue;
+END_ENTITY;
+
+ENTITY IfcJunctionBoxType
+ SUBTYPE OF (IfcFlowFittingType);
+	PredefinedType : IfcJunctionBoxTypeEnum;
+END_ENTITY;
+
+ENTITY IfcLShapeProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	Depth : IfcPositiveLengthMeasure;
+	Width : OPTIONAL IfcPositiveLengthMeasure;
+	Thickness : IfcPositiveLengthMeasure;
+	FilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+	EdgeRadius : OPTIONAL IfcPositiveLengthMeasure;
+	LegSlope : OPTIONAL IfcPlaneAngleMeasure;
+	CentreOfGravityInX : OPTIONAL IfcPositiveLengthMeasure;
+	CentreOfGravityInY : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR21 : Thickness < Depth;
+	WR22 : NOT(EXISTS(Width)) OR (Thickness < Width);
+END_ENTITY;
+
+ENTITY IfcLaborResource
+ SUBTYPE OF (IfcConstructionResource);
+	SkillSet : OPTIONAL IfcText;
+END_ENTITY;
+
+ENTITY IfcLampType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcLampTypeEnum;
+END_ENTITY;
+
+ENTITY IfcLibraryInformation;
+	Name : IfcLabel;
+	Version : OPTIONAL IfcLabel;
+	Publisher : OPTIONAL IfcOrganization;
+	VersionDate : OPTIONAL IfcCalendarDate;
+	LibraryReference : OPTIONAL SET [1:?] OF IfcLibraryReference;
+END_ENTITY;
+
+ENTITY IfcLibraryReference
+ SUBTYPE OF (IfcExternalReference);
+ INVERSE
+	ReferenceIntoLibrary : SET [0:1] OF IfcLibraryInformation FOR LibraryReference;
+END_ENTITY;
+
+ENTITY IfcLightDistributionData;
+	MainPlaneAngle : IfcPlaneAngleMeasure;
+	SecondaryPlaneAngle : LIST [1:?] OF IfcPlaneAngleMeasure;
+	LuminousIntensity : LIST [1:?] OF IfcLuminousIntensityDistributionMeasure;
+END_ENTITY;
+
+ENTITY IfcLightFixtureType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcLightFixtureTypeEnum;
+END_ENTITY;
+
+ENTITY IfcLightIntensityDistribution;
+	LightDistributionCurve : IfcLightDistributionCurveEnum;
+	DistributionData : LIST [1:?] OF IfcLightDistributionData;
+END_ENTITY;
+
+ENTITY IfcLightSource
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcLightSourceAmbient
+	,IfcLightSourceDirectional
+	,IfcLightSourceGoniometric
+	,IfcLightSourcePositional))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Name : OPTIONAL IfcLabel;
+	LightColour : IfcColourRgb;
+	AmbientIntensity : OPTIONAL IfcNormalisedRatioMeasure;
+	Intensity : OPTIONAL IfcNormalisedRatioMeasure;
+END_ENTITY;
+
+ENTITY IfcLightSourceAmbient
+ SUBTYPE OF (IfcLightSource);
+END_ENTITY;
+
+ENTITY IfcLightSourceDirectional
+ SUBTYPE OF (IfcLightSource);
+	Orientation : IfcDirection;
+END_ENTITY;
+
+ENTITY IfcLightSourceGoniometric
+ SUBTYPE OF (IfcLightSource);
+	Position : IfcAxis2Placement3D;
+	ColourAppearance : OPTIONAL IfcColourRgb;
+	ColourTemperature : IfcThermodynamicTemperatureMeasure;
+	LuminousFlux : IfcLuminousFluxMeasure;
+	LightEmissionSource : IfcLightEmissionSourceEnum;
+	LightDistributionDataSource : IfcLightDistributionDataSourceSelect;
+END_ENTITY;
+
+ENTITY IfcLightSourcePositional
+ SUPERTYPE OF (ONEOF
+	(IfcLightSourceSpot))
+ SUBTYPE OF (IfcLightSource);
+	Position : IfcCartesianPoint;
+	Radius : IfcPositiveLengthMeasure;
+	ConstantAttenuation : IfcReal;
+	DistanceAttenuation : IfcReal;
+	QuadricAttenuation : IfcReal;
+END_ENTITY;
+
+ENTITY IfcLightSourceSpot
+ SUBTYPE OF (IfcLightSourcePositional);
+	Orientation : IfcDirection;
+	ConcentrationExponent : OPTIONAL IfcReal;
+	SpreadAngle : IfcPositivePlaneAngleMeasure;
+	BeamWidthAngle : IfcPositivePlaneAngleMeasure;
+END_ENTITY;
+
+ENTITY IfcLine
+ SUBTYPE OF (IfcCurve);
+	Pnt : IfcCartesianPoint;
+	Dir : IfcVector;
+ WHERE
+	WR1 : Dir.Dim = Pnt.Dim;
+END_ENTITY;
+
+ENTITY IfcLinearDimension
+ SUBTYPE OF (IfcDimensionCurveDirectedCallout);
+END_ENTITY;
+
+ENTITY IfcLocalPlacement
+ SUBTYPE OF (IfcObjectPlacement);
+	PlacementRelTo : OPTIONAL IfcObjectPlacement;
+	RelativePlacement : IfcAxis2Placement;
+ WHERE
+	WR21 : IfcCorrectLocalPlacement(RelativePlacement, PlacementRelTo);
+END_ENTITY;
+
+ENTITY IfcLocalTime;
+	HourComponent : IfcHourInDay;
+	MinuteComponent : OPTIONAL IfcMinuteInHour;
+	SecondComponent : OPTIONAL IfcSecondInMinute;
+	Zone : OPTIONAL IfcCoordinatedUniversalTimeOffset;
+	DaylightSavingOffset : OPTIONAL IfcDaylightSavingHour;
+ WHERE
+	WR21 : IfcValidTime (SELF);
+END_ENTITY;
+
+ENTITY IfcLoop
+ SUPERTYPE OF (ONEOF
+	(IfcEdgeLoop
+	,IfcPolyLoop
+	,IfcVertexLoop))
+ SUBTYPE OF (IfcTopologicalRepresentationItem);
+END_ENTITY;
+
+ENTITY IfcManifoldSolidBrep
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcFacetedBrep
+	,IfcFacetedBrepWithVoids))
+ SUBTYPE OF (IfcSolidModel);
+	Outer : IfcClosedShell;
+END_ENTITY;
+
+ENTITY IfcMappedItem
+ SUBTYPE OF (IfcRepresentationItem);
+	MappingSource : IfcRepresentationMap;
+	MappingTarget : IfcCartesianTransformationOperator;
+END_ENTITY;
+
+ENTITY IfcMaterial;
+	Name : IfcLabel;
+ INVERSE
+	HasRepresentation : SET [0:1] OF IfcMaterialDefinitionRepresentation FOR RepresentedMaterial;
+	ClassifiedAs : SET [0:1] OF IfcMaterialClassificationRelationship FOR ClassifiedMaterial;
+END_ENTITY;
+
+ENTITY IfcMaterialClassificationRelationship;
+	MaterialClassifications : SET [1:?] OF IfcClassificationNotationSelect;
+	ClassifiedMaterial : IfcMaterial;
+END_ENTITY;
+
+ENTITY IfcMaterialDefinitionRepresentation
+ SUBTYPE OF (IfcProductRepresentation);
+	RepresentedMaterial : IfcMaterial;
+ WHERE
+	WR11 : SIZEOF(QUERY(temp <* Representations | 
+               (NOT('IFC2X3.IFCSTYLEDREPRESENTATION' IN TYPEOF(temp)))
+             )) = 0;
+END_ENTITY;
+
+ENTITY IfcMaterialLayer;
+	Material : OPTIONAL IfcMaterial;
+	LayerThickness : IfcPositiveLengthMeasure;
+	IsVentilated : OPTIONAL IfcLogical;
+ INVERSE
+	ToMaterialLayerSet : IfcMaterialLayerSet FOR MaterialLayers;
+END_ENTITY;
+
+ENTITY IfcMaterialLayerSet;
+	MaterialLayers : LIST [1:?] OF IfcMaterialLayer;
+	LayerSetName : OPTIONAL IfcLabel;
+ DERIVE
+	TotalThickness : IfcLengthMeasure := IfcMlsTotalThickness(SELF);
+END_ENTITY;
+
+ENTITY IfcMaterialLayerSetUsage;
+	ForLayerSet : IfcMaterialLayerSet;
+	LayerSetDirection : IfcLayerSetDirectionEnum;
+	DirectionSense : IfcDirectionSenseEnum;
+	OffsetFromReferenceLine : IfcLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcMaterialList;
+	Materials : LIST [1:?] OF IfcMaterial;
+END_ENTITY;
+
+ENTITY IfcMaterialProperties
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcExtendedMaterialProperties
+	,IfcFuelProperties
+	,IfcGeneralMaterialProperties
+	,IfcHygroscopicMaterialProperties
+	,IfcMechanicalMaterialProperties
+	,IfcOpticalMaterialProperties
+	,IfcProductsOfCombustionProperties
+	,IfcThermalMaterialProperties
+	,IfcWaterProperties));
+	Material : IfcMaterial;
+END_ENTITY;
+
+ENTITY IfcMeasureWithUnit;
+	ValueComponent : IfcValue;
+	UnitComponent : IfcUnit;
+END_ENTITY;
+
+ENTITY IfcMechanicalConcreteMaterialProperties
+ SUBTYPE OF (IfcMechanicalMaterialProperties);
+	CompressiveStrength : OPTIONAL IfcPressureMeasure;
+	MaxAggregateSize : OPTIONAL IfcPositiveLengthMeasure;
+	AdmixturesDescription : OPTIONAL IfcText;
+	Workability : OPTIONAL IfcText;
+	ProtectivePoreRatio : OPTIONAL IfcNormalisedRatioMeasure;
+	WaterImpermeability : OPTIONAL IfcText;
+END_ENTITY;
+
+ENTITY IfcMechanicalFastener
+ SUBTYPE OF (IfcFastener);
+	NominalDiameter : OPTIONAL IfcPositiveLengthMeasure;
+	NominalLength : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcMechanicalFastenerType
+ SUBTYPE OF (IfcFastenerType);
+END_ENTITY;
+
+ENTITY IfcMechanicalMaterialProperties
+ SUPERTYPE OF (ONEOF
+	(IfcMechanicalConcreteMaterialProperties
+	,IfcMechanicalSteelMaterialProperties))
+ SUBTYPE OF (IfcMaterialProperties);
+	DynamicViscosity : OPTIONAL IfcDynamicViscosityMeasure;
+	YoungModulus : OPTIONAL IfcModulusOfElasticityMeasure;
+	ShearModulus : OPTIONAL IfcModulusOfElasticityMeasure;
+	PoissonRatio : OPTIONAL IfcPositiveRatioMeasure;
+	ThermalExpansionCoefficient : OPTIONAL IfcThermalExpansionCoefficientMeasure;
+ UNIQUE
+	UR11 : Material;
+ WHERE
+	WR21 : NOT(EXISTS(YoungModulus)) OR (YoungModulus >= 0.0);
+	WR22 : NOT(EXISTS(ShearModulus)) OR (ShearModulus >= 0.0);
+END_ENTITY;
+
+ENTITY IfcMechanicalSteelMaterialProperties
+ SUBTYPE OF (IfcMechanicalMaterialProperties);
+	YieldStress : OPTIONAL IfcPressureMeasure;
+	UltimateStress : OPTIONAL IfcPressureMeasure;
+	UltimateStrain : OPTIONAL IfcPositiveRatioMeasure;
+	HardeningModule : OPTIONAL IfcModulusOfElasticityMeasure;
+	ProportionalStress : OPTIONAL IfcPressureMeasure;
+	PlasticStrain : OPTIONAL IfcPositiveRatioMeasure;
+	Relaxations : OPTIONAL SET [1:?] OF IfcRelaxation;
+ WHERE
+	WR31 : NOT(EXISTS(YieldStress)) OR (YieldStress >= 0.);
+	WR32 : NOT(EXISTS(UltimateStress)) OR (UltimateStress >= 0.);
+	WR33 : NOT(EXISTS(HardeningModule)) OR (HardeningModule >= 0.);
+	WR34 : NOT(EXISTS(ProportionalStress)) OR (ProportionalStress >= 0.);
+END_ENTITY;
+
+ENTITY IfcMember
+ SUBTYPE OF (IfcBuildingElement);
+END_ENTITY;
+
+ENTITY IfcMemberType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcMemberTypeEnum;
+END_ENTITY;
+
+ENTITY IfcMetric
+ SUBTYPE OF (IfcConstraint);
+	Benchmark : IfcBenchmarkEnum;
+	ValueSource : OPTIONAL IfcLabel;
+	DataValue : IfcMetricValueSelect;
+END_ENTITY;
+
+ENTITY IfcMonetaryUnit;
+	Currency : IfcCurrencyEnum;
+END_ENTITY;
+
+ENTITY IfcMotorConnectionType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcMotorConnectionTypeEnum;
+END_ENTITY;
+
+ENTITY IfcMove
+ SUBTYPE OF (IfcTask);
+	MoveFrom : IfcSpatialStructureElement;
+	MoveTo : IfcSpatialStructureElement;
+	PunchList : OPTIONAL LIST [1:?] OF UNIQUE IfcText;
+ WHERE
+	WR1 : SIZEOF(SELF\IfcProcess.OperatesOn) >= 1;
+	WR2 : SIZEOF(QUERY(temp <* OperatesOn |
+              SIZEOF(QUERY(temp2 <* temp.RelatedObjects |
+                ('IFC2X3.IFCACTOR' IN TYPEOF (temp2)) OR
+                ('IFC2X3.IFCEQUIPMENTELEMENT' IN TYPEOF (temp2)) OR
+                ('IFC2X3.IFCFURNISHINGELEMENT' IN TYPEOF (temp2)) )) >=1
+              )) >= 1;
+	WR3 : EXISTS(SELF\IfcRoot.Name);
+END_ENTITY;
+
+ENTITY IfcNamedUnit
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcContextDependentUnit
+	,IfcConversionBasedUnit
+	,IfcSIUnit));
+	Dimensions : IfcDimensionalExponents;
+	UnitType : IfcUnitEnum;
+ WHERE
+	WR1 : IfcCorrectDimensions (SELF.UnitType, SELF.Dimensions);
+END_ENTITY;
+
+ENTITY IfcObject
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcActor
+	,IfcControl
+	,IfcGroup
+	,IfcProcess
+	,IfcProduct
+	,IfcProject
+	,IfcResource))
+ SUBTYPE OF (IfcObjectDefinition);
+	ObjectType : OPTIONAL IfcLabel;
+ INVERSE
+	IsDefinedBy : SET [0:?] OF IfcRelDefines FOR RelatedObjects;
+ WHERE
+	WR1 : SIZEOF(QUERY(temp <* IsDefinedBy | 'IFC2X3.IFCRELDEFINESBYTYPE' IN TYPEOF(temp))) <= 1;
+END_ENTITY;
+
+ENTITY IfcObjectDefinition
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcObject
+	,IfcTypeObject))
+ SUBTYPE OF (IfcRoot);
+ INVERSE
+	HasAssignments : SET [0:?] OF IfcRelAssigns FOR RelatedObjects;
+	IsDecomposedBy : SET [0:?] OF IfcRelDecomposes FOR RelatingObject;
+	Decomposes : SET [0:1] OF IfcRelDecomposes FOR RelatedObjects;
+	HasAssociations : SET [0:?] OF IfcRelAssociates FOR RelatedObjects;
+END_ENTITY;
+
+ENTITY IfcObjectPlacement
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcGridPlacement
+	,IfcLocalPlacement));
+ INVERSE
+	PlacesObject : SET [1:1] OF IfcProduct FOR ObjectPlacement;
+	ReferencedByPlacements : SET [0:?] OF IfcLocalPlacement FOR PlacementRelTo;
+END_ENTITY;
+
+ENTITY IfcObjective
+ SUBTYPE OF (IfcConstraint);
+	BenchmarkValues : OPTIONAL IfcMetric;
+	ResultValues : OPTIONAL IfcMetric;
+	ObjectiveQualifier : IfcObjectiveEnum;
+	UserDefinedQualifier : OPTIONAL IfcLabel;
+ WHERE
+	WR21 : (ObjectiveQualifier <> IfcObjectiveEnum.USERDEFINED) OR
+             ((ObjectiveQualifier = IfcObjectiveEnum.USERDEFINED) AND EXISTS(SELF\IfcObjective.UserDefinedQualifier));
+END_ENTITY;
+
+ENTITY IfcOccupant
+ SUBTYPE OF (IfcActor);
+	PredefinedType : IfcOccupantTypeEnum;
+ WHERE
+	WR31 : NOT(PredefinedType = IfcOccupantTypeEnum.USERDEFINED) 
+             OR EXISTS(SELF\IfcObject.ObjectType);
+END_ENTITY;
+
+ENTITY IfcOffsetCurve2D
+ SUBTYPE OF (IfcCurve);
+	BasisCurve : IfcCurve;
+	Distance : IfcLengthMeasure;
+	SelfIntersect : LOGICAL;
+ WHERE
+	WR1 : BasisCurve.Dim = 2;
+END_ENTITY;
+
+ENTITY IfcOffsetCurve3D
+ SUBTYPE OF (IfcCurve);
+	BasisCurve : IfcCurve;
+	Distance : IfcLengthMeasure;
+	SelfIntersect : LOGICAL;
+	RefDirection : IfcDirection;
+ WHERE
+	WR1 : BasisCurve.Dim = 3;
+END_ENTITY;
+
+ENTITY IfcOneDirectionRepeatFactor
+ SUPERTYPE OF (ONEOF
+	(IfcTwoDirectionRepeatFactor))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	RepeatFactor : IfcVector;
+END_ENTITY;
+
+ENTITY IfcOpenShell
+ SUBTYPE OF (IfcConnectedFaceSet);
+END_ENTITY;
+
+ENTITY IfcOpeningElement
+ SUBTYPE OF (IfcFeatureElementSubtraction);
+ INVERSE
+	HasFillings : SET [0:?] OF IfcRelFillsElement FOR RelatingOpeningElement;
+END_ENTITY;
+
+ENTITY IfcOpticalMaterialProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	VisibleTransmittance : OPTIONAL IfcPositiveRatioMeasure;
+	SolarTransmittance : OPTIONAL IfcPositiveRatioMeasure;
+	ThermalIrTransmittance : OPTIONAL IfcPositiveRatioMeasure;
+	ThermalIrEmissivityBack : OPTIONAL IfcPositiveRatioMeasure;
+	ThermalIrEmissivityFront : OPTIONAL IfcPositiveRatioMeasure;
+	VisibleReflectanceBack : OPTIONAL IfcPositiveRatioMeasure;
+	VisibleReflectanceFront : OPTIONAL IfcPositiveRatioMeasure;
+	SolarReflectanceFront : OPTIONAL IfcPositiveRatioMeasure;
+	SolarReflectanceBack : OPTIONAL IfcPositiveRatioMeasure;
+ UNIQUE
+	UR11 : Material;
+END_ENTITY;
+
+ENTITY IfcOrderAction
+ SUBTYPE OF (IfcTask);
+	ActionID : IfcIdentifier;
+ UNIQUE
+	UR2 : ActionID;
+END_ENTITY;
+
+ENTITY IfcOrganization;
+	Id : OPTIONAL IfcIdentifier;
+	Name : IfcLabel;
+	Description : OPTIONAL IfcText;
+	Roles : OPTIONAL LIST [1:?] OF IfcActorRole;
+	Addresses : OPTIONAL LIST [1:?] OF IfcAddress;
+ INVERSE
+	IsRelatedBy : SET [0:?] OF IfcOrganizationRelationship FOR RelatedOrganizations;
+	Relates : SET [0:?] OF IfcOrganizationRelationship FOR RelatingOrganization;
+	Engages : SET [0:?] OF IfcPersonAndOrganization FOR TheOrganization;
+END_ENTITY;
+
+ENTITY IfcOrganizationRelationship;
+	Name : IfcLabel;
+	Description : OPTIONAL IfcText;
+	RelatingOrganization : IfcOrganization;
+	RelatedOrganizations : SET [1:?] OF IfcOrganization;
+END_ENTITY;
+
+ENTITY IfcOrientedEdge
+ SUBTYPE OF (IfcEdge);
+	EdgeElement : IfcEdge;
+	Orientation : BOOLEAN;
+ DERIVE
+	SELF\IfcEdge.EdgeStart : IfcVertex := IfcBooleanChoose 
+                               (Orientation, EdgeElement.EdgeStart, EdgeElement.EdgeEnd);
+	SELF\IfcEdge.EdgeEnd : IfcVertex := IfcBooleanChoose 
+                               (Orientation, EdgeElement.EdgeEnd, EdgeElement.EdgeStart);
+ WHERE
+	WR1 : NOT('IFC2X3.IFCORIENTEDEDGE' IN TYPEOF(EdgeElement));
+END_ENTITY;
+
+ENTITY IfcOutletType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcOutletTypeEnum;
+END_ENTITY;
+
+ENTITY IfcOwnerHistory;
+	OwningUser : IfcPersonAndOrganization;
+	OwningApplication : IfcApplication;
+	State : OPTIONAL IfcStateEnum;
+	ChangeAction : IfcChangeActionEnum;
+	LastModifiedDate : OPTIONAL IfcTimeStamp;
+	LastModifyingUser : OPTIONAL IfcPersonAndOrganization;
+	LastModifyingApplication : OPTIONAL IfcApplication;
+	CreationDate : IfcTimeStamp;
+END_ENTITY;
+
+ENTITY IfcParameterizedProfileDef
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCShapeProfileDef
+	,IfcCircleProfileDef
+	,IfcCraneRailAShapeProfileDef
+	,IfcCraneRailFShapeProfileDef
+	,IfcEllipseProfileDef
+	,IfcIShapeProfileDef
+	,IfcLShapeProfileDef
+	,IfcRectangleProfileDef
+	,IfcTShapeProfileDef
+	,IfcTrapeziumProfileDef
+	,IfcUShapeProfileDef
+	,IfcZShapeProfileDef))
+ SUBTYPE OF (IfcProfileDef);
+	Position : IfcAxis2Placement2D;
+END_ENTITY;
+
+ENTITY IfcPath
+ SUBTYPE OF (IfcTopologicalRepresentationItem);
+	EdgeList : LIST [1:?] OF UNIQUE IfcOrientedEdge;
+ WHERE
+	WR1 : IfcPathHeadToTail(SELF);
+END_ENTITY;
+
+ENTITY IfcPerformanceHistory
+ SUBTYPE OF (IfcControl);
+	LifeCyclePhase : IfcLabel;
+END_ENTITY;
+
+ENTITY IfcPermeableCoveringProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	OperationType : IfcPermeableCoveringOperationEnum;
+	PanelPosition : IfcWindowPanelPositionEnum;
+	FrameDepth : OPTIONAL IfcPositiveLengthMeasure;
+	FrameThickness : OPTIONAL IfcPositiveLengthMeasure;
+	ShapeAspectStyle : OPTIONAL IfcShapeAspect;
+END_ENTITY;
+
+ENTITY IfcPermit
+ SUBTYPE OF (IfcControl);
+	PermitID : IfcIdentifier;
+ UNIQUE
+	UR2 : PermitID;
+END_ENTITY;
+
+ENTITY IfcPerson;
+	Id : OPTIONAL IfcIdentifier;
+	FamilyName : OPTIONAL IfcLabel;
+	GivenName : OPTIONAL IfcLabel;
+	MiddleNames : OPTIONAL LIST [1:?] OF IfcLabel;
+	PrefixTitles : OPTIONAL LIST [1:?] OF IfcLabel;
+	SuffixTitles : OPTIONAL LIST [1:?] OF IfcLabel;
+	Roles : OPTIONAL LIST [1:?] OF IfcActorRole;
+	Addresses : OPTIONAL LIST [1:?] OF IfcAddress;
+ INVERSE
+	EngagedIn : SET [0:?] OF IfcPersonAndOrganization FOR ThePerson;
+ WHERE
+	WR1 : EXISTS(FamilyName) OR 
+            EXISTS(GivenName);
+END_ENTITY;
+
+ENTITY IfcPersonAndOrganization;
+	ThePerson : IfcPerson;
+	TheOrganization : IfcOrganization;
+	Roles : OPTIONAL LIST [1:?] OF IfcActorRole;
+END_ENTITY;
+
+ENTITY IfcPhysicalComplexQuantity
+ SUBTYPE OF (IfcPhysicalQuantity);
+	HasQuantities : SET [1:?] OF IfcPhysicalQuantity;
+	Discrimination : IfcLabel;
+	Quality : OPTIONAL IfcLabel;
+	Usage : OPTIONAL IfcLabel;
+ WHERE
+	WR21 : SIZEOF(QUERY(temp <* HasQuantities | SELF :=: temp)) = 0;
+END_ENTITY;
+
+ENTITY IfcPhysicalQuantity
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcPhysicalComplexQuantity
+	,IfcPhysicalSimpleQuantity));
+	Name : IfcLabel;
+	Description : OPTIONAL IfcText;
+ INVERSE
+	PartOfComplex : SET [0:1] OF IfcPhysicalComplexQuantity FOR HasQuantities;
+END_ENTITY;
+
+ENTITY IfcPhysicalSimpleQuantity
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcQuantityArea
+	,IfcQuantityCount
+	,IfcQuantityLength
+	,IfcQuantityTime
+	,IfcQuantityVolume
+	,IfcQuantityWeight))
+ SUBTYPE OF (IfcPhysicalQuantity);
+	Unit : OPTIONAL IfcNamedUnit;
+END_ENTITY;
+
+ENTITY IfcPile
+ SUBTYPE OF (IfcBuildingElement);
+	PredefinedType : IfcPileTypeEnum;
+	ConstructionType : OPTIONAL IfcPileConstructionEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcPileTypeEnum.USERDEFINED) OR ((PredefinedType = IfcPileTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcObject.ObjectType));
+END_ENTITY;
+
+ENTITY IfcPipeFittingType
+ SUBTYPE OF (IfcFlowFittingType);
+	PredefinedType : IfcPipeFittingTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcPipeFittingTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcPipeFittingTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcPipeSegmentType
+ SUBTYPE OF (IfcFlowSegmentType);
+	PredefinedType : IfcPipeSegmentTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcPipeSegmentTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcPipeSegmentTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcPixelTexture
+ SUBTYPE OF (IfcSurfaceTexture);
+	Width : IfcInteger;
+	Height : IfcInteger;
+	ColourComponents : IfcInteger;
+	Pixel : LIST [1:?] OF BINARY(32);
+ WHERE
+	WR21 : Width >= 1;
+	WR22 : Height >= 1;
+	WR23 : {1 <= ColourComponents <= 4};
+	WR24 : SIZEOF(Pixel) = (Width * Height);
+END_ENTITY;
+
+ENTITY IfcPlacement
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcAxis1Placement
+	,IfcAxis2Placement2D
+	,IfcAxis2Placement3D))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Location : IfcCartesianPoint;
+ DERIVE
+	Dim : IfcDimensionCount := Location.Dim;
+END_ENTITY;
+
+ENTITY IfcPlanarBox
+ SUBTYPE OF (IfcPlanarExtent);
+	Placement : IfcAxis2Placement;
+END_ENTITY;
+
+ENTITY IfcPlanarExtent
+ SUPERTYPE OF (ONEOF
+	(IfcPlanarBox))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	SizeInX : IfcLengthMeasure;
+	SizeInY : IfcLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcPlane
+ SUBTYPE OF (IfcElementarySurface);
+END_ENTITY;
+
+ENTITY IfcPlate
+ SUBTYPE OF (IfcBuildingElement);
+END_ENTITY;
+
+ENTITY IfcPlateType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcPlateTypeEnum;
+ WHERE
+	WR1 : SIZEOF (QUERY(temp <* SELF\IfcObjectDefinition.HasAssociations | 'IFC2X3.IFCRELASSOCIATESMATERIAL' IN TYPEOF(temp) )) = 1;
+END_ENTITY;
+
+ENTITY IfcPoint
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCartesianPoint
+	,IfcPointOnCurve
+	,IfcPointOnSurface))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+END_ENTITY;
+
+ENTITY IfcPointOnCurve
+ SUBTYPE OF (IfcPoint);
+	BasisCurve : IfcCurve;
+	PointParameter : IfcParameterValue;
+ DERIVE
+	Dim : IfcDimensionCount := BasisCurve.Dim;
+END_ENTITY;
+
+ENTITY IfcPointOnSurface
+ SUBTYPE OF (IfcPoint);
+	BasisSurface : IfcSurface;
+	PointParameterU : IfcParameterValue;
+	PointParameterV : IfcParameterValue;
+ DERIVE
+	Dim : IfcDimensionCount := BasisSurface.Dim;
+END_ENTITY;
+
+ENTITY IfcPolyLoop
+ SUBTYPE OF (IfcLoop);
+	Polygon : LIST [3:?] OF UNIQUE IfcCartesianPoint;
+ WHERE
+	WR21 : SIZEOF(QUERY(Temp <* Polygon | Temp.Dim <> Polygon[1].Dim)) = 0;
+END_ENTITY;
+
+ENTITY IfcPolygonalBoundedHalfSpace
+ SUBTYPE OF (IfcHalfSpaceSolid);
+	Position : IfcAxis2Placement3D;
+	PolygonalBoundary : IfcBoundedCurve;
+ WHERE
+	WR41 : PolygonalBoundary.Dim = 2;
+	WR42 : SIZEOF(TYPEOF(PolygonalBoundary) * [
+               'IFC2X3.IFCPOLYLINE', 
+               'IFC2X3.IFCCOMPOSITECURVE']
+             ) = 1;
+END_ENTITY;
+
+ENTITY IfcPolyline
+ SUBTYPE OF (IfcBoundedCurve);
+	Points : LIST [2:?] OF IfcCartesianPoint;
+ WHERE
+	WR41 : SIZEOF(QUERY(Temp <* Points | Temp.Dim <> Points[1].Dim)) = 0;
+END_ENTITY;
+
+ENTITY IfcPort
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDistributionPort))
+ SUBTYPE OF (IfcProduct);
+ INVERSE
+	ContainedIn : IfcRelConnectsPortToElement FOR RelatingPort;
+	ConnectedFrom : SET [0:1] OF IfcRelConnectsPorts FOR RelatedPort;
+	ConnectedTo : SET [0:1] OF IfcRelConnectsPorts FOR RelatingPort;
+END_ENTITY;
+
+ENTITY IfcPostalAddress
+ SUBTYPE OF (IfcAddress);
+	InternalLocation : OPTIONAL IfcLabel;
+	AddressLines : OPTIONAL LIST [1:?] OF IfcLabel;
+	PostalBox : OPTIONAL IfcLabel;
+	Town : OPTIONAL IfcLabel;
+	Region : OPTIONAL IfcLabel;
+	PostalCode : OPTIONAL IfcLabel;
+	Country : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : EXISTS (InternalLocation) OR 
+            EXISTS (AddressLines) OR
+            EXISTS (PostalBox) OR
+            EXISTS (PostalCode) OR
+            EXISTS (Town) OR 
+            EXISTS (Region) OR  
+            EXISTS (Country);
+END_ENTITY;
+
+ENTITY IfcPreDefinedColour
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDraughtingPreDefinedColour))
+ SUBTYPE OF (IfcPreDefinedItem);
+END_ENTITY;
+
+ENTITY IfcPreDefinedCurveFont
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDraughtingPreDefinedCurveFont))
+ SUBTYPE OF (IfcPreDefinedItem);
+END_ENTITY;
+
+ENTITY IfcPreDefinedDimensionSymbol
+ SUBTYPE OF (IfcPreDefinedSymbol);
+ WHERE
+	WR31 : SELF\IfcPreDefinedItem.Name IN ['arc length','conical taper','counterbore',
+                  'countersink','depth','diameter','plus minus','radius',
+                  'slope','spherical diameter','spherical radius','square'];
+END_ENTITY;
+
+ENTITY IfcPreDefinedItem
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcPreDefinedColour
+	,IfcPreDefinedCurveFont
+	,IfcPreDefinedSymbol
+	,IfcPreDefinedTextFont));
+	Name : IfcLabel;
+END_ENTITY;
+
+ENTITY IfcPreDefinedPointMarkerSymbol
+ SUBTYPE OF (IfcPreDefinedSymbol);
+ WHERE
+	WR31 : SELF\IfcPreDefinedItem.Name IN ['asterisk','circle','dot','plus','square','triangle','x'];
+END_ENTITY;
+
+ENTITY IfcPreDefinedSymbol
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcPreDefinedDimensionSymbol
+	,IfcPreDefinedPointMarkerSymbol
+	,IfcPreDefinedTerminatorSymbol))
+ SUBTYPE OF (IfcPreDefinedItem);
+END_ENTITY;
+
+ENTITY IfcPreDefinedTerminatorSymbol
+ SUBTYPE OF (IfcPreDefinedSymbol);
+ WHERE
+	WR31 : SELF\IfcPreDefinedItem.Name IN ['blanked arrow','blanked box',
+                 'blanked dot','dimension origin','filled arrow','filled box',
+                 'filled dot','integral symbol','open arrow','slash','unfilled arrow'];
+END_ENTITY;
+
+ENTITY IfcPreDefinedTextFont
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDraughtingPreDefinedTextFont
+	,IfcTextStyleFontModel))
+ SUBTYPE OF (IfcPreDefinedItem);
+END_ENTITY;
+
+ENTITY IfcPresentationLayerAssignment
+ SUPERTYPE OF (ONEOF
+	(IfcPresentationLayerWithStyle));
+	Name : IfcLabel;
+	Description : OPTIONAL IfcText;
+	AssignedItems : SET [1:?] OF IfcLayeredItem;
+	Identifier : OPTIONAL IfcIdentifier;
+END_ENTITY;
+
+ENTITY IfcPresentationLayerWithStyle
+ SUBTYPE OF (IfcPresentationLayerAssignment);
+	LayerOn : LOGICAL;
+	LayerFrozen : LOGICAL;
+	LayerBlocked : LOGICAL;
+	LayerStyles : SET [0:?] OF IfcPresentationStyleSelect;
+END_ENTITY;
+
+ENTITY IfcPresentationStyle
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCurveStyle
+	,IfcFillAreaStyle
+	,IfcSurfaceStyle
+	,IfcSymbolStyle
+	,IfcTextStyle));
+	Name : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcPresentationStyleAssignment;
+	Styles : SET [1:?] OF IfcPresentationStyleSelect;
+END_ENTITY;
+
+ENTITY IfcProcedure
+ SUBTYPE OF (IfcProcess);
+	ProcedureID : IfcIdentifier;
+	ProcedureType : IfcProcedureTypeEnum;
+	UserDefinedProcedureType : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : SIZEOF(QUERY(temp <* SELF\IfcObjectDefinition.Decomposes | NOT('IFC2X3.IFCRELNESTS' IN TYPEOF(temp)))) = 0;
+	WR2 : SIZEOF(QUERY(temp <* SELF\IfcObjectDefinition.IsDecomposedBy | NOT('IFC2X3.IFCRELNESTS' IN TYPEOF(temp)))) = 0;
+	WR3 : EXISTS(SELF\IfcRoot.Name);
+	WR4 : (ProcedureType <> IfcProcedureTypeEnum.USERDEFINED) OR
+            ((ProcedureType = IfcProcedureTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcProcedure.UserDefinedProcedureType));
+END_ENTITY;
+
+ENTITY IfcProcess
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcProcedure
+	,IfcTask))
+ SUBTYPE OF (IfcObject);
+ INVERSE
+	OperatesOn : SET [0:?] OF IfcRelAssignsToProcess FOR RelatingProcess;
+	IsSuccessorFrom : SET [0:?] OF IfcRelSequence FOR RelatedProcess;
+	IsPredecessorTo : SET [0:?] OF IfcRelSequence FOR RelatingProcess;
+END_ENTITY;
+
+ENTITY IfcProduct
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcAnnotation
+	,IfcElement
+	,IfcGrid
+	,IfcPort
+	,IfcProxy
+	,IfcSpatialStructureElement
+	,IfcStructuralActivity
+	,IfcStructuralItem))
+ SUBTYPE OF (IfcObject);
+	ObjectPlacement : OPTIONAL IfcObjectPlacement;
+	Representation : OPTIONAL IfcProductRepresentation;
+ INVERSE
+	ReferencedBy : SET [0:?] OF IfcRelAssignsToProduct FOR RelatingProduct;
+ WHERE
+	WR1 : (EXISTS(Representation) AND EXISTS(ObjectPlacement))
+                        OR (EXISTS(Representation) AND 
+                           (NOT('IFC2X3.IFCPRODUCTDEFINITIONSHAPE' IN TYPEOF(Representation))))
+                        OR (NOT(EXISTS(Representation)));
+END_ENTITY;
+
+ENTITY IfcProductDefinitionShape
+ SUBTYPE OF (IfcProductRepresentation);
+ INVERSE
+	ShapeOfProduct : SET [1:1] OF IfcProduct FOR Representation;
+	HasShapeAspects : SET [0:?] OF IfcShapeAspect FOR PartOfProductDefinitionShape;
+ WHERE
+	WR11 : SIZEOF(QUERY(temp <* Representations | 
+               (NOT('IFC2X3.IFCSHAPEMODEL' IN TYPEOF(temp)))
+             )) = 0;
+END_ENTITY;
+
+ENTITY IfcProductRepresentation
+ SUPERTYPE OF (ONEOF
+	(IfcMaterialDefinitionRepresentation
+	,IfcProductDefinitionShape));
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+	Representations : LIST [1:?] OF IfcRepresentation;
+END_ENTITY;
+
+ENTITY IfcProductsOfCombustionProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	SpecificHeatCapacity : OPTIONAL IfcSpecificHeatCapacityMeasure;
+	N20Content : OPTIONAL IfcPositiveRatioMeasure;
+	COContent : OPTIONAL IfcPositiveRatioMeasure;
+	CO2Content : OPTIONAL IfcPositiveRatioMeasure;
+ UNIQUE
+	UR11 : Material;
+END_ENTITY;
+
+ENTITY IfcProfileDef
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcArbitraryClosedProfileDef
+	,IfcArbitraryOpenProfileDef
+	,IfcCompositeProfileDef
+	,IfcDerivedProfileDef
+	,IfcParameterizedProfileDef));
+	ProfileType : IfcProfileTypeEnum;
+	ProfileName : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcProfileProperties
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcGeneralProfileProperties
+	,IfcRibPlateProfileProperties));
+	ProfileName : OPTIONAL IfcLabel;
+	ProfileDefinition : OPTIONAL IfcProfileDef;
+END_ENTITY;
+
+ENTITY IfcProject
+ SUBTYPE OF (IfcObject);
+	LongName : OPTIONAL IfcLabel;
+	Phase : OPTIONAL IfcLabel;
+	RepresentationContexts : SET [1:?] OF IfcRepresentationContext;
+	UnitsInContext : IfcUnitAssignment;
+ WHERE
+	WR31 : EXISTS(SELF\IfcRoot.Name);
+	WR32 : SIZEOF(QUERY(Temp <* RepresentationContexts |
+              'IFC2X3.IFCGEOMETRICREPRESENTATIONSUBCONTEXT' IN TYPEOF(Temp)
+             )) = 0;
+	WR33 : SIZEOF(SELF\IfcObjectDefinition.Decomposes) = 0;
+END_ENTITY;
+
+ENTITY IfcProjectOrder
+ SUBTYPE OF (IfcControl);
+	ID : IfcIdentifier;
+	PredefinedType : IfcProjectOrderTypeEnum;
+	Status : OPTIONAL IfcLabel;
+ UNIQUE
+	UR2 : ID;
+END_ENTITY;
+
+ENTITY IfcProjectOrderRecord
+ SUBTYPE OF (IfcControl);
+	Records : LIST [1:?] OF UNIQUE IfcRelAssignsToProjectOrder;
+	PredefinedType : IfcProjectOrderRecordTypeEnum;
+END_ENTITY;
+
+ENTITY IfcProjectionCurve
+ SUBTYPE OF (IfcAnnotationCurveOccurrence);
+END_ENTITY;
+
+ENTITY IfcProjectionElement
+ SUBTYPE OF (IfcFeatureElementAddition);
+END_ENTITY;
+
+ENTITY IfcProperty
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcComplexProperty
+	,IfcSimpleProperty));
+	Name : IfcIdentifier;
+	Description : OPTIONAL IfcText;
+ INVERSE
+	PropertyForDependance : SET [0:?] OF IfcPropertyDependencyRelationship FOR DependingProperty;
+	PropertyDependsOn : SET [0:?] OF IfcPropertyDependencyRelationship FOR DependantProperty;
+	PartOfComplex : SET [0:1] OF IfcComplexProperty FOR HasProperties;
+END_ENTITY;
+
+ENTITY IfcPropertyBoundedValue
+ SUBTYPE OF (IfcSimpleProperty);
+	UpperBoundValue : OPTIONAL IfcValue;
+	LowerBoundValue : OPTIONAL IfcValue;
+	Unit : OPTIONAL IfcUnit;
+ WHERE
+	WR21 : NOT(EXISTS(UpperBoundValue)) OR NOT(EXISTS(LowerBoundValue)) OR
+             (TYPEOF(UpperBoundValue) = TYPEOF(LowerBoundValue));
+	WR22 : EXISTS(UpperBoundValue) OR EXISTS(LowerBoundValue);
+END_ENTITY;
+
+ENTITY IfcPropertyConstraintRelationship;
+	RelatingConstraint : IfcConstraint;
+	RelatedProperties : SET [1:?] OF IfcProperty;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+END_ENTITY;
+
+ENTITY IfcPropertyDefinition
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcPropertySetDefinition))
+ SUBTYPE OF (IfcRoot);
+ INVERSE
+	HasAssociations : SET [0:?] OF IfcRelAssociates FOR RelatedObjects;
+END_ENTITY;
+
+ENTITY IfcPropertyDependencyRelationship;
+	DependingProperty : IfcProperty;
+	DependantProperty : IfcProperty;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+	Expression : OPTIONAL IfcText;
+ WHERE
+	WR1 : DependingProperty :<>: DependantProperty;
+END_ENTITY;
+
+ENTITY IfcPropertyEnumeratedValue
+ SUBTYPE OF (IfcSimpleProperty);
+	EnumerationValues : LIST [1:?] OF IfcValue;
+	EnumerationReference : OPTIONAL IfcPropertyEnumeration;
+ WHERE
+	WR1 : NOT(EXISTS(EnumerationReference)) OR 
+               (SIZEOF(QUERY(temp <* EnumerationValues |
+                temp IN EnumerationReference.EnumerationValues))
+                = SIZEOF(EnumerationValues));
+END_ENTITY;
+
+ENTITY IfcPropertyEnumeration;
+	Name : IfcLabel;
+	EnumerationValues : LIST [1:?] OF UNIQUE IfcValue;
+	Unit : OPTIONAL IfcUnit;
+ UNIQUE
+	UR1 : Name;
+ WHERE
+	WR01 : SIZEOF(QUERY(temp <* SELF.EnumerationValues | 
+               NOT(TYPEOF(SELF.EnumerationValues[1]) = TYPEOF(temp))
+               )) = 0;
+END_ENTITY;
+
+ENTITY IfcPropertyListValue
+ SUBTYPE OF (IfcSimpleProperty);
+	ListValues : LIST [1:?] OF IfcValue;
+	Unit : OPTIONAL IfcUnit;
+ WHERE
+	WR31 : SIZEOF(QUERY(temp <* SELF.ListValues | 
+               NOT(TYPEOF(SELF.ListValues[1]) = TYPEOF(temp))
+               )) = 0;
+END_ENTITY;
+
+ENTITY IfcPropertyReferenceValue
+ SUBTYPE OF (IfcSimpleProperty);
+	UsageName : OPTIONAL IfcLabel;
+	PropertyReference : IfcObjectReferenceSelect;
+END_ENTITY;
+
+ENTITY IfcPropertySet
+ SUBTYPE OF (IfcPropertySetDefinition);
+	HasProperties : SET [1:?] OF IfcProperty;
+ WHERE
+	WR31 : EXISTS(SELF\IfcRoot.Name);
+	WR32 : IfcUniquePropertyName(HasProperties);
+END_ENTITY;
+
+ENTITY IfcPropertySetDefinition
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcDoorLiningProperties
+	,IfcDoorPanelProperties
+	,IfcElementQuantity
+	,IfcEnergyProperties
+	,IfcFluidFlowProperties
+	,IfcPermeableCoveringProperties
+	,IfcPropertySet
+	,IfcReinforcementDefinitionProperties
+	,IfcServiceLifeFactor
+	,IfcSoundProperties
+	,IfcSoundValue
+	,IfcSpaceThermalLoadProperties
+	,IfcWindowLiningProperties
+	,IfcWindowPanelProperties))
+ SUBTYPE OF (IfcPropertyDefinition);
+ INVERSE
+	PropertyDefinitionOf : SET [0:1] OF IfcRelDefinesByProperties FOR RelatingPropertyDefinition;
+	DefinesType : SET [0:1] OF IfcTypeObject FOR HasPropertySets;
+END_ENTITY;
+
+ENTITY IfcPropertySingleValue
+ SUBTYPE OF (IfcSimpleProperty);
+	NominalValue : OPTIONAL IfcValue;
+	Unit : OPTIONAL IfcUnit;
+END_ENTITY;
+
+ENTITY IfcPropertyTableValue
+ SUBTYPE OF (IfcSimpleProperty);
+	DefiningValues : LIST [1:?] OF UNIQUE IfcValue;
+	DefinedValues : LIST [1:?] OF IfcValue;
+	Expression : OPTIONAL IfcText;
+	DefiningUnit : OPTIONAL IfcUnit;
+	DefinedUnit : OPTIONAL IfcUnit;
+ WHERE
+	WR1 : SIZEOF(DefiningValues) = SIZEOF(DefinedValues);
+	WR2 : SIZEOF(QUERY(temp <* SELF.DefiningValues | TYPEOF(temp) <> TYPEOF(SELF.DefiningValues[1])))=0;
+	WR3 : SIZEOF(QUERY(temp <* SELF.DefinedValues | TYPEOF(temp) <> TYPEOF(SELF.DefinedValues[1])))=0;
+END_ENTITY;
+
+ENTITY IfcProtectiveDeviceType
+ SUBTYPE OF (IfcFlowControllerType);
+	PredefinedType : IfcProtectiveDeviceTypeEnum;
+END_ENTITY;
+
+ENTITY IfcProxy
+ SUBTYPE OF (IfcProduct);
+	ProxyType : IfcObjectTypeEnum;
+	Tag : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : EXISTS(SELF\IfcRoot.Name);
+END_ENTITY;
+
+ENTITY IfcPumpType
+ SUBTYPE OF (IfcFlowMovingDeviceType);
+	PredefinedType : IfcPumpTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcPumpTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcPumpTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcQuantityArea
+ SUBTYPE OF (IfcPhysicalSimpleQuantity);
+	AreaValue : IfcAreaMeasure;
+ WHERE
+	WR21 : NOT(EXISTS(SELF\IfcPhysicalSimpleQuantity.Unit)) OR
+                (SELF\IfcPhysicalSimpleQuantity.Unit.UnitType = IfcUnitEnum.AREAUNIT);
+	WR22 : AreaValue >= 0.;
+END_ENTITY;
+
+ENTITY IfcQuantityCount
+ SUBTYPE OF (IfcPhysicalSimpleQuantity);
+	CountValue : IfcCountMeasure;
+ WHERE
+	WR21 : CountValue >= 0.;
+END_ENTITY;
+
+ENTITY IfcQuantityLength
+ SUBTYPE OF (IfcPhysicalSimpleQuantity);
+	LengthValue : IfcLengthMeasure;
+ WHERE
+	WR21 : NOT(EXISTS(SELF\IfcPhysicalSimpleQuantity.Unit)) OR
+                (SELF\IfcPhysicalSimpleQuantity.Unit.UnitType = IfcUnitEnum.LENGTHUNIT);
+	WR22 : LengthValue >= 0.;
+END_ENTITY;
+
+ENTITY IfcQuantityTime
+ SUBTYPE OF (IfcPhysicalSimpleQuantity);
+	TimeValue : IfcTimeMeasure;
+ WHERE
+	WR21 : NOT(EXISTS(SELF\IfcPhysicalSimpleQuantity.Unit)) OR
+                (SELF\IfcPhysicalSimpleQuantity.Unit.UnitType = IfcUnitEnum.TIMEUNIT);
+	WR22 : TimeValue >= 0.;
+END_ENTITY;
+
+ENTITY IfcQuantityVolume
+ SUBTYPE OF (IfcPhysicalSimpleQuantity);
+	VolumeValue : IfcVolumeMeasure;
+ WHERE
+	WR21 : NOT(EXISTS(SELF\IfcPhysicalSimpleQuantity.Unit)) OR
+                (SELF\IfcPhysicalSimpleQuantity.Unit.UnitType = IfcUnitEnum.VOLUMEUNIT);
+	WR22 : VolumeValue >= 0.;
+END_ENTITY;
+
+ENTITY IfcQuantityWeight
+ SUBTYPE OF (IfcPhysicalSimpleQuantity);
+	WeightValue : IfcMassMeasure;
+ WHERE
+	WR21 : NOT(EXISTS(SELF\IfcPhysicalSimpleQuantity.Unit)) OR
+                (SELF\IfcPhysicalSimpleQuantity.Unit.UnitType = IfcUnitEnum.MASSUNIT);
+	WR22 : WeightValue >= 0.;
+END_ENTITY;
+
+ENTITY IfcRadiusDimension
+ SUBTYPE OF (IfcDimensionCurveDirectedCallout);
+END_ENTITY;
+
+ENTITY IfcRailing
+ SUBTYPE OF (IfcBuildingElement);
+	PredefinedType : OPTIONAL IfcRailingTypeEnum;
+END_ENTITY;
+
+ENTITY IfcRailingType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcRailingTypeEnum;
+END_ENTITY;
+
+ENTITY IfcRamp
+ SUBTYPE OF (IfcBuildingElement);
+	ShapeType : IfcRampTypeEnum;
+ WHERE
+	WR1 : (HIINDEX(SELF\IfcObjectDefinition.IsDecomposedBy) = 0) OR 
+            ((HIINDEX(SELF\IfcObjectDefinition.IsDecomposedBy) = 1) AND (NOT(EXISTS(SELF\IfcProduct.Representation))));
+END_ENTITY;
+
+ENTITY IfcRampFlight
+ SUBTYPE OF (IfcBuildingElement);
+END_ENTITY;
+
+ENTITY IfcRampFlightType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcRampFlightTypeEnum;
+END_ENTITY;
+
+ENTITY IfcRationalBezierCurve
+ SUBTYPE OF (IfcBezierCurve);
+	WeightsData : LIST [2:?] OF REAL;
+ DERIVE
+	Weights : ARRAY [0:255] OF REAL := IfcListToArray(WeightsData,0,SELF\IfcBSplineCurve.UpperIndexOnControlPoints);
+ WHERE
+	WR1 : SIZEOF(WeightsData) = SIZEOF(SELF\IfcBSplineCurve.ControlPointsList);
+	WR2 : IfcCurveWeightsPositive(SELF);
+END_ENTITY;
+
+ENTITY IfcRectangleHollowProfileDef
+ SUBTYPE OF (IfcRectangleProfileDef);
+	WallThickness : IfcPositiveLengthMeasure;
+	InnerFilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+	OuterFilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR31 : (WallThickness < (SELF\IfcRectangleProfileDef.XDim/2.)) AND 
+             (WallThickness < (SELF\IfcRectangleProfileDef.YDim/2.));
+	WR32 : NOT(EXISTS(OuterFilletRadius)) OR 
+             ((OuterFilletRadius <= (SELF\IfcRectangleProfileDef.XDim/2.)) AND 
+              (OuterFilletRadius <= (SELF\IfcRectangleProfileDef.YDim/2.)));
+	WR33 : NOT(EXISTS(InnerFilletRadius)) OR 
+             ((InnerFilletRadius <= (SELF\IfcRectangleProfileDef.XDim/2. - WallThickness)) AND 
+              (InnerFilletRadius <= (SELF\IfcRectangleProfileDef.YDim/2. - WallThickness)));
+END_ENTITY;
+
+ENTITY IfcRectangleProfileDef
+ SUPERTYPE OF (ONEOF
+	(IfcRectangleHollowProfileDef
+	,IfcRoundedRectangleProfileDef))
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	XDim : IfcPositiveLengthMeasure;
+	YDim : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcRectangularPyramid
+ SUBTYPE OF (IfcCsgPrimitive3D);
+	XLength : IfcPositiveLengthMeasure;
+	YLength : IfcPositiveLengthMeasure;
+	Height : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcRectangularTrimmedSurface
+ SUBTYPE OF (IfcBoundedSurface);
+	BasisSurface : IfcSurface;
+	U1 : IfcParameterValue;
+	V1 : IfcParameterValue;
+	U2 : IfcParameterValue;
+	V2 : IfcParameterValue;
+	Usense : BOOLEAN;
+	Vsense : BOOLEAN;
+ DERIVE
+	Dim : IfcDimensionCount := BasisSurface.Dim;
+ WHERE
+	WR1 : U1 <> U2;
+	WR2 : V1 <> V2;
+	WR3 : (('IFC2X3.IFCELEMENTARYSURFACE' IN TYPEOF(BasisSurface)) AND
+                     (NOT ('IFC2X3.IFCPLANE' IN TYPEOF(BasisSurface)))) OR
+                     ('IFC2X3.IFCSURFACEOFREVOLUTION' IN TYPEOF(BasisSurface)) OR
+                     (Usense = (U2 > U1));
+	WR4 : Vsense = (V2 > V1);
+END_ENTITY;
+
+ENTITY IfcReferencesValueDocument;
+	ReferencedDocument : IfcDocumentSelect;
+	ReferencingValues : SET [1:?] OF IfcAppliedValue;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+END_ENTITY;
+
+ENTITY IfcRegularTimeSeries
+ SUBTYPE OF (IfcTimeSeries);
+	TimeStep : IfcTimeMeasure;
+	Values : LIST [1:?] OF IfcTimeSeriesValue;
+END_ENTITY;
+
+ENTITY IfcReinforcementBarProperties;
+	TotalCrossSectionArea : IfcAreaMeasure;
+	SteelGrade : IfcLabel;
+	BarSurface : OPTIONAL IfcReinforcingBarSurfaceEnum;
+	EffectiveDepth : OPTIONAL IfcLengthMeasure;
+	NominalBarDiameter : OPTIONAL IfcPositiveLengthMeasure;
+	BarCount : OPTIONAL IfcCountMeasure;
+END_ENTITY;
+
+ENTITY IfcReinforcementDefinitionProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	DefinitionType : OPTIONAL IfcLabel;
+	ReinforcementSectionDefinitions : LIST [1:?] OF IfcSectionReinforcementProperties;
+END_ENTITY;
+
+ENTITY IfcReinforcingBar
+ SUBTYPE OF (IfcReinforcingElement);
+	NominalDiameter : IfcPositiveLengthMeasure;
+	CrossSectionArea : IfcAreaMeasure;
+	BarLength : OPTIONAL IfcPositiveLengthMeasure;
+	BarRole : IfcReinforcingBarRoleEnum;
+	BarSurface : OPTIONAL IfcReinforcingBarSurfaceEnum;
+ WHERE
+	WR1 : (BarRole <> IfcReinforcingBarRoleEnum.USERDEFINED) OR ((BarRole = IfcReinforcingBarRoleEnum.USERDEFINED) AND EXISTS(SELF\IfcObject.ObjectType));
+END_ENTITY;
+
+ENTITY IfcReinforcingElement
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcReinforcingBar
+	,IfcReinforcingMesh
+	,IfcTendon
+	,IfcTendonAnchor))
+ SUBTYPE OF (IfcBuildingElementComponent);
+	SteelGrade : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcReinforcingMesh
+ SUBTYPE OF (IfcReinforcingElement);
+	MeshLength : OPTIONAL IfcPositiveLengthMeasure;
+	MeshWidth : OPTIONAL IfcPositiveLengthMeasure;
+	LongitudinalBarNominalDiameter : IfcPositiveLengthMeasure;
+	TransverseBarNominalDiameter : IfcPositiveLengthMeasure;
+	LongitudinalBarCrossSectionArea : IfcAreaMeasure;
+	TransverseBarCrossSectionArea : IfcAreaMeasure;
+	LongitudinalBarSpacing : IfcPositiveLengthMeasure;
+	TransverseBarSpacing : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcRelAggregates
+ SUBTYPE OF (IfcRelDecomposes);
+END_ENTITY;
+
+ENTITY IfcRelAssigns
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcRelAssignsToActor
+	,IfcRelAssignsToControl
+	,IfcRelAssignsToGroup
+	,IfcRelAssignsToProcess
+	,IfcRelAssignsToProduct
+	,IfcRelAssignsToResource))
+ SUBTYPE OF (IfcRelationship);
+	RelatedObjects : SET [1:?] OF IfcObjectDefinition;
+	RelatedObjectsType : OPTIONAL IfcObjectTypeEnum;
+ WHERE
+	WR1 : IfcCorrectObjectAssignment(RelatedObjectsType, RelatedObjects);
+END_ENTITY;
+
+ENTITY IfcRelAssignsTasks
+ SUBTYPE OF (IfcRelAssignsToControl);
+	TimeForTask : OPTIONAL IfcScheduleTimeControl;
+ WHERE
+	WR1 : HIINDEX(SELF\IfcRelAssigns.RelatedObjects) = 1;
+	WR2 : 'IFC2X3.IFCTASK' IN TYPEOF(SELF\IfcRelAssigns.RelatedObjects[1]);
+	WR3 : 'IFC2X3.IFCWORKCONTROL' IN TYPEOF(SELF\IfcRelAssignsToControl.RelatingControl);
+END_ENTITY;
+
+ENTITY IfcRelAssignsToActor
+ SUPERTYPE OF (ONEOF
+	(IfcRelOccupiesSpaces))
+ SUBTYPE OF (IfcRelAssigns);
+	RelatingActor : IfcActor;
+	ActingRole : OPTIONAL IfcActorRole;
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcRelAssigns.RelatedObjects | RelatingActor :=: Temp)) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssignsToControl
+ SUPERTYPE OF (ONEOF
+	(IfcRelAssignsTasks
+	,IfcRelAssignsToProjectOrder
+	,IfcRelSchedulesCostItems))
+ SUBTYPE OF (IfcRelAssigns);
+	RelatingControl : IfcControl;
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcRelAssigns.RelatedObjects | RelatingControl :=: Temp)) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssignsToGroup
+ SUBTYPE OF (IfcRelAssigns);
+	RelatingGroup : IfcGroup;
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcRelAssigns.RelatedObjects | RelatingGroup :=: Temp)) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssignsToProcess
+ SUBTYPE OF (IfcRelAssigns);
+	RelatingProcess : IfcProcess;
+	QuantityInProcess : OPTIONAL IfcMeasureWithUnit;
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcRelAssigns.RelatedObjects | RelatingProcess :=: Temp)) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssignsToProduct
+ SUBTYPE OF (IfcRelAssigns);
+	RelatingProduct : IfcProduct;
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcRelAssigns.RelatedObjects | RelatingProduct :=: Temp)) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssignsToProjectOrder
+ SUBTYPE OF (IfcRelAssignsToControl);
+END_ENTITY;
+
+ENTITY IfcRelAssignsToResource
+ SUBTYPE OF (IfcRelAssigns);
+	RelatingResource : IfcResource;
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcRelAssigns.RelatedObjects | RelatingResource :=: Temp)) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssociates
+ SUPERTYPE OF (ONEOF
+	(IfcRelAssociatesAppliedValue
+	,IfcRelAssociatesApproval
+	,IfcRelAssociatesClassification
+	,IfcRelAssociatesConstraint
+	,IfcRelAssociatesDocument
+	,IfcRelAssociatesLibrary
+	,IfcRelAssociatesMaterial
+	,IfcRelAssociatesProfileProperties))
+ SUBTYPE OF (IfcRelationship);
+	RelatedObjects : SET [1:?] OF IfcRoot;
+ WHERE
+	WR21 : SIZEOF(QUERY(temp <* RelatedObjects |
+              NOT(('IFC2X3.IFCOBJECTDEFINITION' IN TYPEOF(temp)) 
+               OR ('IFC2X3.IFCPROPERTYDEFINITION' IN TYPEOF(temp)))
+              )) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesAppliedValue
+ SUBTYPE OF (IfcRelAssociates);
+	RelatingAppliedValue : IfcAppliedValue;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesApproval
+ SUBTYPE OF (IfcRelAssociates);
+	RelatingApproval : IfcApproval;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesClassification
+ SUBTYPE OF (IfcRelAssociates);
+	RelatingClassification : IfcClassificationNotationSelect;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesConstraint
+ SUBTYPE OF (IfcRelAssociates);
+	Intent : IfcLabel;
+	RelatingConstraint : IfcConstraint;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesDocument
+ SUBTYPE OF (IfcRelAssociates);
+	RelatingDocument : IfcDocumentSelect;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesLibrary
+ SUBTYPE OF (IfcRelAssociates);
+	RelatingLibrary : IfcLibrarySelect;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesMaterial
+ SUBTYPE OF (IfcRelAssociates);
+	RelatingMaterial : IfcMaterialSelect;
+ WHERE
+	WR21 : SIZEOF(QUERY(temp <* SELF\IfcRelAssociates.RelatedObjects | 
+             ('IFC2X3.IFCFEATUREELEMENTSUBTRACTION' IN TYPEOF(temp))
+               OR ('IFC2X3.IFCVIRTUALELEMENT' IN TYPEOF(temp))
+             )) = 0;
+	WR22 : SIZEOF(QUERY(temp <* SELF\IfcRelAssociates.RelatedObjects | 
+             (NOT('IFC2X3.IFCPRODUCT' IN TYPEOF(temp)) AND NOT('IFC2X3.IFCTYPEPRODUCT' IN TYPEOF(temp)))
+             )) = 0;
+END_ENTITY;
+
+ENTITY IfcRelAssociatesProfileProperties
+ SUBTYPE OF (IfcRelAssociates);
+	RelatingProfileProperties : IfcProfileProperties;
+	ProfileSectionLocation : OPTIONAL IfcShapeAspect;
+	ProfileOrientation : OPTIONAL IfcOrientationSelect;
+END_ENTITY;
+
+ENTITY IfcRelConnects
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcRelConnectsElements
+	,IfcRelConnectsPortToElement
+	,IfcRelConnectsPorts
+	,IfcRelConnectsStructuralActivity
+	,IfcRelConnectsStructuralElement
+	,IfcRelConnectsStructuralMember
+	,IfcRelContainedInSpatialStructure
+	,IfcRelCoversBldgElements
+	,IfcRelCoversSpaces
+	,IfcRelFillsElement
+	,IfcRelFlowControlElements
+	,IfcRelInteractionRequirements
+	,IfcRelProjectsElement
+	,IfcRelReferencedInSpatialStructure
+	,IfcRelSequence
+	,IfcRelServicesBuildings
+	,IfcRelSpaceBoundary
+	,IfcRelVoidsElement))
+ SUBTYPE OF (IfcRelationship);
+END_ENTITY;
+
+ENTITY IfcRelConnectsElements
+ SUPERTYPE OF (ONEOF
+	(IfcRelConnectsPathElements
+	,IfcRelConnectsWithRealizingElements))
+ SUBTYPE OF (IfcRelConnects);
+	ConnectionGeometry : OPTIONAL IfcConnectionGeometry;
+	RelatingElement : IfcElement;
+	RelatedElement : IfcElement;
+ WHERE
+	WR31 : RelatingElement :<>: RelatedElement;
+END_ENTITY;
+
+ENTITY IfcRelConnectsPathElements
+ SUBTYPE OF (IfcRelConnectsElements);
+	RelatingPriorities : LIST [0:?] OF INTEGER;
+	RelatedPriorities : LIST [0:?] OF INTEGER;
+	RelatedConnectionType : IfcConnectionTypeEnum;
+	RelatingConnectionType : IfcConnectionTypeEnum;
+ DERIVE
+	RelatedLayerCount : INTEGER := IfcNoOfLayers(SELF\IfcRelConnectsElements.RelatedElement);
+	RelatingLayerCount : INTEGER := IfcNoOfLayers(SELF\IfcRelConnectsElements.RelatingElement);
+END_ENTITY;
+
+ENTITY IfcRelConnectsPortToElement
+ SUBTYPE OF (IfcRelConnects);
+	RelatingPort : IfcPort;
+	RelatedElement : IfcElement;
+END_ENTITY;
+
+ENTITY IfcRelConnectsPorts
+ SUBTYPE OF (IfcRelConnects);
+	RelatingPort : IfcPort;
+	RelatedPort : IfcPort;
+	RealizingElement : OPTIONAL IfcElement;
+END_ENTITY;
+
+ENTITY IfcRelConnectsStructuralActivity
+ SUBTYPE OF (IfcRelConnects);
+	RelatingElement : IfcStructuralActivityAssignmentSelect;
+	RelatedStructuralActivity : IfcStructuralActivity;
+END_ENTITY;
+
+ENTITY IfcRelConnectsStructuralElement
+ SUBTYPE OF (IfcRelConnects);
+	RelatingElement : IfcElement;
+	RelatedStructuralMember : IfcStructuralMember;
+END_ENTITY;
+
+ENTITY IfcRelConnectsStructuralMember
+ SUPERTYPE OF (ONEOF
+	(IfcRelConnectsWithEccentricity))
+ SUBTYPE OF (IfcRelConnects);
+	RelatingStructuralMember : IfcStructuralMember;
+	RelatedStructuralConnection : IfcStructuralConnection;
+	AppliedCondition : OPTIONAL IfcBoundaryCondition;
+	AdditionalConditions : OPTIONAL IfcStructuralConnectionCondition;
+	SupportedLength : OPTIONAL IfcLengthMeasure;
+	ConditionCoordinateSystem : OPTIONAL IfcAxis2Placement3D;
+END_ENTITY;
+
+ENTITY IfcRelConnectsWithEccentricity
+ SUBTYPE OF (IfcRelConnectsStructuralMember);
+	ConnectionConstraint : IfcConnectionGeometry;
+END_ENTITY;
+
+ENTITY IfcRelConnectsWithRealizingElements
+ SUBTYPE OF (IfcRelConnectsElements);
+	RealizingElements : SET [1:?] OF IfcElement;
+	ConnectionType : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcRelContainedInSpatialStructure
+ SUBTYPE OF (IfcRelConnects);
+	RelatedElements : SET [1:?] OF IfcProduct;
+	RelatingStructure : IfcSpatialStructureElement;
+ WHERE
+	WR31 : SIZEOF(QUERY(temp <* RelatedElements | 'IFC2X3.IFCSPATIALSTRUCTUREELEMENT' IN TYPEOF(temp))) = 0;
+END_ENTITY;
+
+ENTITY IfcRelCoversBldgElements
+ SUBTYPE OF (IfcRelConnects);
+	RelatingBuildingElement : IfcElement;
+	RelatedCoverings : SET [1:?] OF IfcCovering;
+END_ENTITY;
+
+ENTITY IfcRelCoversSpaces
+ SUBTYPE OF (IfcRelConnects);
+	RelatedSpace : IfcSpace;
+	RelatedCoverings : SET [1:?] OF IfcCovering;
+END_ENTITY;
+
+ENTITY IfcRelDecomposes
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcRelAggregates
+	,IfcRelNests))
+ SUBTYPE OF (IfcRelationship);
+	RelatingObject : IfcObjectDefinition;
+	RelatedObjects : SET [1:?] OF IfcObjectDefinition;
+ WHERE
+	WR31 : SIZEOF(QUERY(Temp <* RelatedObjects | RelatingObject :=: Temp)) = 0;
+	WR32 : SIZEOF(QUERY(Temp <* RelatedObjects | 'IFC2X3.IFCTYPEOBJECT' IN TYPEOF(temp))) = 0;
+	WR33 : NOT('IFC2X3.IFCTYPEOBJECT' IN TYPEOF(RelatingObject));
+END_ENTITY;
+
+ENTITY IfcRelDefines
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcRelDefinesByProperties
+	,IfcRelDefinesByType))
+ SUBTYPE OF (IfcRelationship);
+	RelatedObjects : SET [1:?] OF IfcObject;
+END_ENTITY;
+
+ENTITY IfcRelDefinesByProperties
+ SUPERTYPE OF (ONEOF
+	(IfcRelOverridesProperties))
+ SUBTYPE OF (IfcRelDefines);
+	RelatingPropertyDefinition : IfcPropertySetDefinition;
+END_ENTITY;
+
+ENTITY IfcRelDefinesByType
+ SUBTYPE OF (IfcRelDefines);
+	RelatingType : IfcTypeObject;
+END_ENTITY;
+
+ENTITY IfcRelFillsElement
+ SUBTYPE OF (IfcRelConnects);
+	RelatingOpeningElement : IfcOpeningElement;
+	RelatedBuildingElement : IfcElement;
+END_ENTITY;
+
+ENTITY IfcRelFlowControlElements
+ SUBTYPE OF (IfcRelConnects);
+	RelatedControlElements : SET [1:?] OF IfcDistributionControlElement;
+	RelatingFlowElement : IfcDistributionFlowElement;
+END_ENTITY;
+
+ENTITY IfcRelInteractionRequirements
+ SUBTYPE OF (IfcRelConnects);
+	DailyInteraction : OPTIONAL IfcCountMeasure;
+	ImportanceRating : OPTIONAL IfcNormalisedRatioMeasure;
+	LocationOfInteraction : OPTIONAL IfcSpatialStructureElement;
+	RelatedSpaceProgram : IfcSpaceProgram;
+	RelatingSpaceProgram : IfcSpaceProgram;
+END_ENTITY;
+
+ENTITY IfcRelNests
+ SUBTYPE OF (IfcRelDecomposes);
+ WHERE
+	WR1 : SIZEOF(QUERY(Temp <* SELF\IfcRelDecomposes.RelatedObjects | 
+              NOT(TYPEOF(SELF\IfcRelDecomposes.RelatingObject) = TYPEOF(Temp)))) = 0;
+END_ENTITY;
+
+ENTITY IfcRelOccupiesSpaces
+ SUBTYPE OF (IfcRelAssignsToActor);
+END_ENTITY;
+
+ENTITY IfcRelOverridesProperties
+ SUBTYPE OF (IfcRelDefinesByProperties);
+	OverridingProperties : SET [1:?] OF IfcProperty;
+ WHERE
+	WR1 : SIZEOF(SELF\IfcRelDefines.RelatedObjects) = 1;
+END_ENTITY;
+
+ENTITY IfcRelProjectsElement
+ SUBTYPE OF (IfcRelConnects);
+	RelatingElement : IfcElement;
+	RelatedFeatureElement : IfcFeatureElementAddition;
+END_ENTITY;
+
+ENTITY IfcRelReferencedInSpatialStructure
+ SUBTYPE OF (IfcRelConnects);
+	RelatedElements : SET [1:?] OF IfcProduct;
+	RelatingStructure : IfcSpatialStructureElement;
+ WHERE
+	WR31 : SIZEOF(QUERY(temp <* RelatedElements | 'IFC2X3.IFCSPATIALSTRUCTUREELEMENT' IN TYPEOF(temp))) = 0;
+END_ENTITY;
+
+ENTITY IfcRelSchedulesCostItems
+ SUBTYPE OF (IfcRelAssignsToControl);
+ WHERE
+	WR11 : SIZEOF(QUERY(temp <* SELF\IfcRelAssigns.RelatedObjects |
+               NOT('IFC2X3.IFCCOSTITEM' IN TYPEOF(temp))
+               )) = 0;
+	WR12 : 'IFC2X3.IFCCOSTSCHEDULE' IN TYPEOF (SELF\IfcRelAssignsToControl.RelatingControl);
+END_ENTITY;
+
+ENTITY IfcRelSequence
+ SUBTYPE OF (IfcRelConnects);
+	RelatingProcess : IfcProcess;
+	RelatedProcess : IfcProcess;
+	TimeLag : IfcTimeMeasure;
+	SequenceType : IfcSequenceEnum;
+ WHERE
+	WR1 : RelatingProcess :<>: RelatedProcess;
+END_ENTITY;
+
+ENTITY IfcRelServicesBuildings
+ SUBTYPE OF (IfcRelConnects);
+	RelatingSystem : IfcSystem;
+	RelatedBuildings : SET [1:?] OF IfcSpatialStructureElement;
+END_ENTITY;
+
+ENTITY IfcRelSpaceBoundary
+ SUBTYPE OF (IfcRelConnects);
+	RelatingSpace : IfcSpace;
+	RelatedBuildingElement : OPTIONAL IfcElement;
+	ConnectionGeometry : OPTIONAL IfcConnectionGeometry;
+	PhysicalOrVirtualBoundary : IfcPhysicalOrVirtualEnum;
+	InternalOrExternalBoundary : IfcInternalOrExternalEnum;
+ WHERE
+	WR1 : ((PhysicalOrVirtualBoundary = IfcPhysicalOrVirtualEnum.Physical) AND 
+              (EXISTS(RelatedBuildingElement) AND NOT('IFC2X3.IFCVIRTUALELEMENT' IN TYPEOF(RelatedBuildingElement)))) 
+            OR 
+            ((PhysicalOrVirtualBoundary = IfcPhysicalOrVirtualEnum.Virtual) AND 
+              (NOT(EXISTS(RelatedBuildingElement)) OR ('IFC2X3.IFCVIRTUALELEMENT' IN TYPEOF(RelatedBuildingElement)))) 
+            OR 
+             (PhysicalOrVirtualBoundary = IfcPhysicalOrVirtualEnum.NotDefined);
+END_ENTITY;
+
+ENTITY IfcRelVoidsElement
+ SUBTYPE OF (IfcRelConnects);
+	RelatingBuildingElement : IfcElement;
+	RelatedOpeningElement : IfcFeatureElementSubtraction;
+END_ENTITY;
+
+ENTITY IfcRelationship
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcRelAssigns
+	,IfcRelAssociates
+	,IfcRelConnects
+	,IfcRelDecomposes
+	,IfcRelDefines))
+ SUBTYPE OF (IfcRoot);
+END_ENTITY;
+
+ENTITY IfcRelaxation;
+	RelaxationValue : IfcNormalisedRatioMeasure;
+	InitialStress : IfcNormalisedRatioMeasure;
+END_ENTITY;
+
+ENTITY IfcRepresentation
+ SUPERTYPE OF (ONEOF
+	(IfcShapeModel
+	,IfcStyleModel));
+	ContextOfItems : IfcRepresentationContext;
+	RepresentationIdentifier : OPTIONAL IfcLabel;
+	RepresentationType : OPTIONAL IfcLabel;
+	Items : SET [1:?] OF IfcRepresentationItem;
+ INVERSE
+	RepresentationMap : SET [0:1] OF IfcRepresentationMap FOR MappedRepresentation;
+	LayerAssignments : SET [0:?] OF IfcPresentationLayerAssignment FOR Assigneditems;
+	OfProductRepresentation : SET [0:1] OF IfcProductRepresentation FOR Representations;
+END_ENTITY;
+
+ENTITY IfcRepresentationContext
+ SUPERTYPE OF (ONEOF
+	(IfcGeometricRepresentationContext));
+	ContextIdentifier : OPTIONAL IfcLabel;
+	ContextType : OPTIONAL IfcLabel;
+ INVERSE
+	RepresentationsInContext : SET [0:?] OF IfcRepresentation FOR ContextOfItems;
+END_ENTITY;
+
+ENTITY IfcRepresentationItem
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcGeometricRepresentationItem
+	,IfcMappedItem
+	,IfcStyledItem
+	,IfcTopologicalRepresentationItem));
+ INVERSE
+	LayerAssignments : SET [0:?] OF IfcPresentationLayerAssignment FOR AssignedItems;
+	StyledByItem : SET [0:1] OF IfcStyledItem FOR Item;
+END_ENTITY;
+
+ENTITY IfcRepresentationMap;
+	MappingOrigin : IfcAxis2Placement;
+	MappedRepresentation : IfcRepresentation;
+ INVERSE
+	MapUsage : SET [0:?] OF IfcMappedItem FOR MappingSource;
+END_ENTITY;
+
+ENTITY IfcResource
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcConstructionResource))
+ SUBTYPE OF (IfcObject);
+ INVERSE
+	ResourceOf : SET [0:?] OF IfcRelAssignsToResource FOR RelatingResource;
+END_ENTITY;
+
+ENTITY IfcRevolvedAreaSolid
+ SUBTYPE OF (IfcSweptAreaSolid);
+	Axis : IfcAxis1Placement;
+	Angle : IfcPlaneAngleMeasure;
+ DERIVE
+	AxisLine : IfcLine := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcCurve() || IfcLine(Axis.Location, 
+                   IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector(Axis.Z,1.0));
+ WHERE
+	WR31 : Axis.Location.Coordinates[3] = 0.0;
+	WR32 : Axis.Z.DirectionRatios[3] = 0.0;
+END_ENTITY;
+
+ENTITY IfcRibPlateProfileProperties
+ SUBTYPE OF (IfcProfileProperties);
+	Thickness : OPTIONAL IfcPositiveLengthMeasure;
+	RibHeight : OPTIONAL IfcPositiveLengthMeasure;
+	RibWidth : OPTIONAL IfcPositiveLengthMeasure;
+	RibSpacing : OPTIONAL IfcPositiveLengthMeasure;
+	Direction : IfcRibPlateDirectionEnum;
+END_ENTITY;
+
+ENTITY IfcRightCircularCone
+ SUBTYPE OF (IfcCsgPrimitive3D);
+	Height : IfcPositiveLengthMeasure;
+	BottomRadius : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcRightCircularCylinder
+ SUBTYPE OF (IfcCsgPrimitive3D);
+	Height : IfcPositiveLengthMeasure;
+	Radius : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcRoof
+ SUBTYPE OF (IfcBuildingElement);
+	ShapeType : IfcRoofTypeEnum;
+ WHERE
+	WR1 : (HIINDEX(SELF\IfcObjectDefinition.IsDecomposedBy) = 0) OR 
+            ((HIINDEX(SELF\IfcObjectDefinition.IsDecomposedBy) = 1) AND (NOT(EXISTS(SELF\IfcProduct.Representation))));
+END_ENTITY;
+
+ENTITY IfcRoot
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcObjectDefinition
+	,IfcPropertyDefinition
+	,IfcRelationship));
+	GlobalId : IfcGloballyUniqueId;
+	OwnerHistory : IfcOwnerHistory;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+ UNIQUE
+	UR1 : GlobalId;
+END_ENTITY;
+
+ENTITY IfcRoundedEdgeFeature
+ SUBTYPE OF (IfcEdgeFeature);
+	Radius : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcRoundedRectangleProfileDef
+ SUBTYPE OF (IfcRectangleProfileDef);
+	RoundingRadius : IfcPositiveLengthMeasure;
+ WHERE
+	WR31 : ((RoundingRadius <= (SELF\IfcRectangleProfileDef.XDim/2.)) AND 
+              (RoundingRadius <= (SELF\IfcRectangleProfileDef.YDim/2.)));
+END_ENTITY;
+
+ENTITY IfcSIUnit
+ SUBTYPE OF (IfcNamedUnit);
+	Prefix : OPTIONAL IfcSIPrefix;
+	Name : IfcSIUnitName;
+ DERIVE
+	SELF\IfcNamedUnit.Dimensions : IfcDimensionalExponents := IfcDimensionsForSiUnit (SELF.Name);
+END_ENTITY;
+
+ENTITY IfcSanitaryTerminalType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcSanitaryTerminalTypeEnum;
+END_ENTITY;
+
+ENTITY IfcScheduleTimeControl
+ SUBTYPE OF (IfcControl);
+	ActualStart : OPTIONAL IfcDateTimeSelect;
+	EarlyStart : OPTIONAL IfcDateTimeSelect;
+	LateStart : OPTIONAL IfcDateTimeSelect;
+	ScheduleStart : OPTIONAL IfcDateTimeSelect;
+	ActualFinish : OPTIONAL IfcDateTimeSelect;
+	EarlyFinish : OPTIONAL IfcDateTimeSelect;
+	LateFinish : OPTIONAL IfcDateTimeSelect;
+	ScheduleFinish : OPTIONAL IfcDateTimeSelect;
+	ScheduleDuration : OPTIONAL IfcTimeMeasure;
+	ActualDuration : OPTIONAL IfcTimeMeasure;
+	RemainingTime : OPTIONAL IfcTimeMeasure;
+	FreeFloat : OPTIONAL IfcTimeMeasure;
+	TotalFloat : OPTIONAL IfcTimeMeasure;
+	IsCritical : OPTIONAL BOOLEAN;
+	StatusTime : OPTIONAL IfcDateTimeSelect;
+	StartFloat : OPTIONAL IfcTimeMeasure;
+	FinishFloat : OPTIONAL IfcTimeMeasure;
+	Completion : OPTIONAL IfcPositiveRatioMeasure;
+ INVERSE
+	ScheduleTimeControlAssigned : IfcRelAssignsTasks FOR TimeForTask;
+END_ENTITY;
+
+ENTITY IfcSectionProperties;
+	SectionType : IfcSectionTypeEnum;
+	StartProfile : IfcProfileDef;
+	EndProfile : OPTIONAL IfcProfileDef;
+END_ENTITY;
+
+ENTITY IfcSectionReinforcementProperties;
+	LongitudinalStartPosition : IfcLengthMeasure;
+	LongitudinalEndPosition : IfcLengthMeasure;
+	TransversePosition : OPTIONAL IfcLengthMeasure;
+	ReinforcementRole : IfcReinforcingBarRoleEnum;
+	SectionDefinition : IfcSectionProperties;
+	CrossSectionReinforcementDefinitions : SET [1:?] OF IfcReinforcementBarProperties;
+END_ENTITY;
+
+ENTITY IfcSectionedSpine
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	SpineCurve : IfcCompositeCurve;
+	CrossSections : LIST [2:?] OF IfcProfileDef;
+	CrossSectionPositions : LIST [2:?] OF IfcAxis2Placement3D;
+ DERIVE
+	Dim : IfcDimensionCount := 3;
+ WHERE
+	WR1 : SIZEOF(CrossSections) = SIZEOF(CrossSectionPositions);
+	WR2 : SIZEOF(QUERY(temp <* CrossSections | CrossSections[1].ProfileType <> temp.ProfileType)) = 0;
+	WR3 : SpineCurve.Dim = 3;
+END_ENTITY;
+
+ENTITY IfcSensorType
+ SUBTYPE OF (IfcDistributionControlElementType);
+	PredefinedType : IfcSensorTypeEnum;
+END_ENTITY;
+
+ENTITY IfcServiceLife
+ SUBTYPE OF (IfcControl);
+	ServiceLifeType : IfcServiceLifeTypeEnum;
+	ServiceLifeDuration : IfcTimeMeasure;
+END_ENTITY;
+
+ENTITY IfcServiceLifeFactor
+ SUBTYPE OF (IfcPropertySetDefinition);
+	PredefinedType : IfcServiceLifeFactorTypeEnum;
+	UpperValue : OPTIONAL IfcMeasureValue;
+	MostUsedValue : IfcMeasureValue;
+	LowerValue : OPTIONAL IfcMeasureValue;
+ WHERE
+	WR31 : NOT(PredefinedType = IfcServiceLifeFactorTypeEnum.USERDEFINED)
+             OR EXISTS(SELF\IfcObject.ObjectType);
+END_ENTITY;
+
+ENTITY IfcShapeAspect;
+	ShapeRepresentations : LIST [1:?] OF IfcShapeModel;
+	Name : OPTIONAL IfcLabel;
+	Description : OPTIONAL IfcText;
+	ProductDefinitional : LOGICAL;
+	PartOfProductDefinitionShape : IfcProductDefinitionShape;
+END_ENTITY;
+
+ENTITY IfcShapeModel
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcShapeRepresentation
+	,IfcTopologyRepresentation))
+ SUBTYPE OF (IfcRepresentation);
+ INVERSE
+	OfShapeAspect : SET [0:1] OF IfcShapeAspect FOR ShapeRepresentations;
+ WHERE
+	WR11 : (SIZEOF(SELF\IfcRepresentation.OfProductRepresentation) = 1) XOR 
+             (SIZEOF(SELF\IfcRepresentation.RepresentationMap) = 1) XOR
+             (SIZEOF(OfShapeAspect) = 1);
+END_ENTITY;
+
+ENTITY IfcShapeRepresentation
+ SUBTYPE OF (IfcShapeModel);
+ WHERE
+	WR21 : 'IFC2X3.IFCGEOMETRICREPRESENTATIONCONTEXT' 
+             IN TYPEOF(SELF\IfcRepresentation.ContextOfItems);
+	WR22 : SIZEOF(QUERY(temp <* Items | 
+               ('IFC2X3.IFCTOPOLOGICALREPRESENTATIONITEM' IN TYPEOF(temp))
+                 AND (NOT(SIZEOF(
+                   ['IFC2X3.IFCVERTEXPOINT',
+                    'IFC2X3.IFCEDGECURVE',
+                    'IFC2X3.IFCFACESURFACE'] * TYPEOF(temp)) = 1))
+             )) = 0;
+	WR23 : EXISTS(SELF\IfcRepresentation.RepresentationType);
+	WR24 : IfcShapeRepresentationTypes(SELF\IfcRepresentation.RepresentationType, SELF\IfcRepresentation.Items);
+END_ENTITY;
+
+ENTITY IfcShellBasedSurfaceModel
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	SbsmBoundary : SET [1:?] OF IfcShell;
+ DERIVE
+	Dim : IfcDimensionCount := 3;
+END_ENTITY;
+
+ENTITY IfcSimpleProperty
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcPropertyBoundedValue
+	,IfcPropertyEnumeratedValue
+	,IfcPropertyListValue
+	,IfcPropertyReferenceValue
+	,IfcPropertySingleValue
+	,IfcPropertyTableValue))
+ SUBTYPE OF (IfcProperty);
+END_ENTITY;
+
+ENTITY IfcSite
+ SUBTYPE OF (IfcSpatialStructureElement);
+	RefLatitude : OPTIONAL IfcCompoundPlaneAngleMeasure;
+	RefLongitude : OPTIONAL IfcCompoundPlaneAngleMeasure;
+	RefElevation : OPTIONAL IfcLengthMeasure;
+	LandTitleNumber : OPTIONAL IfcLabel;
+	SiteAddress : OPTIONAL IfcPostalAddress;
+END_ENTITY;
+
+ENTITY IfcSlab
+ SUBTYPE OF (IfcBuildingElement);
+	PredefinedType : OPTIONAL IfcSlabTypeEnum;
+ WHERE
+	WR2 : (PredefinedType <> IfcSlabTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcSlabTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcObject.ObjectType));
+END_ENTITY;
+
+ENTITY IfcSlabType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcSlabTypeEnum;
+END_ENTITY;
+
+ENTITY IfcSlippageConnectionCondition
+ SUBTYPE OF (IfcStructuralConnectionCondition);
+	SlippageX : OPTIONAL IfcLengthMeasure;
+	SlippageY : OPTIONAL IfcLengthMeasure;
+	SlippageZ : OPTIONAL IfcLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcSolidModel
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcCsgSolid
+	,IfcManifoldSolidBrep
+	,IfcSweptAreaSolid
+	,IfcSweptDiskSolid))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+ DERIVE
+	Dim : IfcDimensionCount := 3;
+END_ENTITY;
+
+ENTITY IfcSoundProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	IsAttenuating : IfcBoolean;
+	SoundScale : OPTIONAL IfcSoundScaleEnum;
+	SoundValues : LIST [1:8] OF IfcSoundValue;
+END_ENTITY;
+
+ENTITY IfcSoundValue
+ SUBTYPE OF (IfcPropertySetDefinition);
+	SoundLevelTimeSeries : OPTIONAL IfcTimeSeries;
+	Frequency : IfcFrequencyMeasure;
+	SoundLevelSingleValue : OPTIONAL IfcDerivedMeasureValue;
+END_ENTITY;
+
+ENTITY IfcSpace
+ SUBTYPE OF (IfcSpatialStructureElement);
+	InteriorOrExteriorSpace : IfcInternalOrExternalEnum;
+	ElevationWithFlooring : OPTIONAL IfcLengthMeasure;
+ INVERSE
+	HasCoverings : SET [0:?] OF IfcRelCoversSpaces FOR RelatedSpace;
+	BoundedBy : SET [0:?] OF IfcRelSpaceBoundary FOR RelatingSpace;
+END_ENTITY;
+
+ENTITY IfcSpaceHeaterType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcSpaceHeaterTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcSpaceHeaterTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcSpaceHeaterTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcSpaceProgram
+ SUBTYPE OF (IfcControl);
+	SpaceProgramIdentifier : IfcIdentifier;
+	MaxRequiredArea : OPTIONAL IfcAreaMeasure;
+	MinRequiredArea : OPTIONAL IfcAreaMeasure;
+	RequestedLocation : OPTIONAL IfcSpatialStructureElement;
+	StandardRequiredArea : IfcAreaMeasure;
+ INVERSE
+	HasInteractionReqsFrom : SET [0:?] OF IfcRelInteractionRequirements FOR RelatedSpaceProgram;
+	HasInteractionReqsTo : SET [0:?] OF IfcRelInteractionRequirements FOR RelatingSpaceProgram;
+END_ENTITY;
+
+ENTITY IfcSpaceThermalLoadProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	ApplicableValueRatio : OPTIONAL IfcPositiveRatioMeasure;
+	ThermalLoadSource : IfcThermalLoadSourceEnum;
+	PropertySource : IfcPropertySourceEnum;
+	SourceDescription : OPTIONAL IfcText;
+	MaximumValue : IfcPowerMeasure;
+	MinimumValue : OPTIONAL IfcPowerMeasure;
+	ThermalLoadTimeSeriesValues : OPTIONAL IfcTimeSeries;
+	UserDefinedThermalLoadSource : OPTIONAL IfcLabel;
+	UserDefinedPropertySource : OPTIONAL IfcLabel;
+	ThermalLoadType : IfcThermalLoadTypeEnum;
+END_ENTITY;
+
+ENTITY IfcSpaceType
+ SUBTYPE OF (IfcSpatialStructureElementType);
+	PredefinedType : IfcSpaceTypeEnum;
+END_ENTITY;
+
+ENTITY IfcSpatialStructureElement
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBuilding
+	,IfcBuildingStorey
+	,IfcSite
+	,IfcSpace))
+ SUBTYPE OF (IfcProduct);
+	LongName : OPTIONAL IfcLabel;
+	CompositionType : IfcElementCompositionEnum;
+ INVERSE
+	ReferencesElements : SET [0:?] OF IfcRelReferencedInSpatialStructure FOR RelatingStructure;
+	ServicedBySystems : SET [0:?] OF IfcRelServicesBuildings FOR RelatedBuildings;
+	ContainsElements : SET [0:?] OF IfcRelContainedInSpatialStructure FOR RelatingStructure;
+ WHERE
+	WR41 : (HIINDEX(SELF\IfcObjectDefinition.Decomposes) = 1) 
+             AND
+             ('IFC2X3.IFCRELAGGREGATES' IN TYPEOF(SELF\IfcObjectDefinition.Decomposes[1])) 
+             AND
+             (('IFC2X3.IFCPROJECT' IN TYPEOF (SELF\IfcObjectDefinition.Decomposes[1].RelatingObject)) OR
+              ('IFC2X3.IFCSPATIALSTRUCTUREELEMENT' IN TYPEOF (SELF\IfcObjectDefinition.Decomposes[1].RelatingObject))
+             );
+END_ENTITY;
+
+ENTITY IfcSpatialStructureElementType
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcSpaceType))
+ SUBTYPE OF (IfcElementType);
+END_ENTITY;
+
+ENTITY IfcSphere
+ SUBTYPE OF (IfcCsgPrimitive3D);
+	Radius : IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcStackTerminalType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcStackTerminalTypeEnum;
+END_ENTITY;
+
+ENTITY IfcStair
+ SUBTYPE OF (IfcBuildingElement);
+	ShapeType : IfcStairTypeEnum;
+ WHERE
+	WR1 : (HIINDEX(SELF\IfcObjectDefinition.IsDecomposedBy) = 0) OR 
+            ((HIINDEX(SELF\IfcObjectDefinition.IsDecomposedBy) = 1) AND (NOT(EXISTS(SELF\IfcProduct.Representation))));
+END_ENTITY;
+
+ENTITY IfcStairFlight
+ SUBTYPE OF (IfcBuildingElement);
+	NumberOfRiser : OPTIONAL INTEGER;
+	NumberOfTreads : OPTIONAL INTEGER;
+	RiserHeight : OPTIONAL IfcPositiveLengthMeasure;
+	TreadLength : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcStairFlightType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcStairFlightTypeEnum;
+END_ENTITY;
+
+ENTITY IfcStructuralAction
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralLinearAction
+	,IfcStructuralPlanarAction
+	,IfcStructuralPointAction))
+ SUBTYPE OF (IfcStructuralActivity);
+	DestabilizingLoad : BOOLEAN;
+	CausedBy : OPTIONAL IfcStructuralReaction;
+END_ENTITY;
+
+ENTITY IfcStructuralActivity
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralAction
+	,IfcStructuralReaction))
+ SUBTYPE OF (IfcProduct);
+	AppliedLoad : IfcStructuralLoad;
+	GlobalOrLocal : IfcGlobalOrLocalEnum;
+ INVERSE
+	AssignedToStructuralItem : IfcRelConnectsStructuralActivity FOR RelatedStructuralActivity;
+END_ENTITY;
+
+ENTITY IfcStructuralAnalysisModel
+ SUBTYPE OF (IfcSystem);
+	PredefinedType : IfcAnalysisModelTypeEnum;
+	OrientationOf2DPlane : OPTIONAL IfcAxis2Placement3D;
+	LoadedBy : OPTIONAL SET [1:?] OF IfcStructuralLoadGroup;
+	HasResults : OPTIONAL SET [1:?] OF IfcStructuralResultGroup;
+END_ENTITY;
+
+ENTITY IfcStructuralConnection
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralCurveConnection
+	,IfcStructuralPointConnection
+	,IfcStructuralSurfaceConnection))
+ SUBTYPE OF (IfcStructuralItem);
+	AppliedCondition : OPTIONAL IfcBoundaryCondition;
+ INVERSE
+	ConnectsStructuralMembers : SET [1:?] OF IfcRelConnectsStructuralMember FOR RelatedStructuralConnection;
+END_ENTITY;
+
+ENTITY IfcStructuralConnectionCondition
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcFailureConnectionCondition
+	,IfcSlippageConnectionCondition));
+	Name : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcStructuralCurveConnection
+ SUBTYPE OF (IfcStructuralConnection);
+END_ENTITY;
+
+ENTITY IfcStructuralCurveMember
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralCurveMemberVarying))
+ SUBTYPE OF (IfcStructuralMember);
+	PredefinedType : IfcStructuralCurveTypeEnum;
+END_ENTITY;
+
+ENTITY IfcStructuralCurveMemberVarying
+ SUBTYPE OF (IfcStructuralCurveMember);
+END_ENTITY;
+
+ENTITY IfcStructuralItem
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralConnection
+	,IfcStructuralMember))
+ SUBTYPE OF (IfcProduct);
+ INVERSE
+	AssignedStructuralActivity : SET [0:?] OF IfcRelConnectsStructuralActivity FOR RelatingElement;
+END_ENTITY;
+
+ENTITY IfcStructuralLinearAction
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralLinearActionVarying))
+ SUBTYPE OF (IfcStructuralAction);
+	ProjectedOrTrue : IfcProjectedOrTrueLengthEnum;
+ WHERE
+	WR61 : SIZEOF(['IFC2X3.IFCSTRUCTURALLOADLINEARFORCE',
+                     'IFC2X3.IFCSTRUCTURALLOADTEMPERATURE']
+             * TYPEOF(SELF\IfcStructuralActivity.AppliedLoad)) = 1;
+END_ENTITY;
+
+ENTITY IfcStructuralLinearActionVarying
+ SUBTYPE OF (IfcStructuralLinearAction);
+	VaryingAppliedLoadLocation : IfcShapeAspect;
+	SubsequentAppliedLoads : LIST [1:?] OF IfcStructuralLoad;
+ DERIVE
+	VaryingAppliedLoads : LIST [2:?] OF IfcStructuralLoad := IfcAddToBeginOfList(SELF\IfcStructuralActivity.AppliedLoad, SubsequentAppliedLoads);
+END_ENTITY;
+
+ENTITY IfcStructuralLoad
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralLoadStatic));
+	Name : OPTIONAL IfcLabel;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadGroup
+ SUBTYPE OF (IfcGroup);
+	PredefinedType : IfcLoadGroupTypeEnum;
+	ActionType : IfcActionTypeEnum;
+	ActionSource : IfcActionSourceTypeEnum;
+	Coefficient : OPTIONAL IfcPositiveRatioMeasure;
+	Purpose : OPTIONAL IfcLabel;
+ INVERSE
+	SourceOfResultGroup : SET [0:1] OF IfcStructuralResultGroup FOR ResultForLoadGroup;
+	LoadGroupFor : SET [0:?] OF IfcStructuralAnalysisModel FOR LoadedBy;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadLinearForce
+ SUBTYPE OF (IfcStructuralLoadStatic);
+	LinearForceX : OPTIONAL IfcLinearForceMeasure;
+	LinearForceY : OPTIONAL IfcLinearForceMeasure;
+	LinearForceZ : OPTIONAL IfcLinearForceMeasure;
+	LinearMomentX : OPTIONAL IfcLinearMomentMeasure;
+	LinearMomentY : OPTIONAL IfcLinearMomentMeasure;
+	LinearMomentZ : OPTIONAL IfcLinearMomentMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadPlanarForce
+ SUBTYPE OF (IfcStructuralLoadStatic);
+	PlanarForceX : OPTIONAL IfcPlanarForceMeasure;
+	PlanarForceY : OPTIONAL IfcPlanarForceMeasure;
+	PlanarForceZ : OPTIONAL IfcPlanarForceMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadSingleDisplacement
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralLoadSingleDisplacementDistortion))
+ SUBTYPE OF (IfcStructuralLoadStatic);
+	DisplacementX : OPTIONAL IfcLengthMeasure;
+	DisplacementY : OPTIONAL IfcLengthMeasure;
+	DisplacementZ : OPTIONAL IfcLengthMeasure;
+	RotationalDisplacementRX : OPTIONAL IfcPlaneAngleMeasure;
+	RotationalDisplacementRY : OPTIONAL IfcPlaneAngleMeasure;
+	RotationalDisplacementRZ : OPTIONAL IfcPlaneAngleMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadSingleDisplacementDistortion
+ SUBTYPE OF (IfcStructuralLoadSingleDisplacement);
+	Distortion : OPTIONAL IfcCurvatureMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadSingleForce
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralLoadSingleForceWarping))
+ SUBTYPE OF (IfcStructuralLoadStatic);
+	ForceX : OPTIONAL IfcForceMeasure;
+	ForceY : OPTIONAL IfcForceMeasure;
+	ForceZ : OPTIONAL IfcForceMeasure;
+	MomentX : OPTIONAL IfcTorqueMeasure;
+	MomentY : OPTIONAL IfcTorqueMeasure;
+	MomentZ : OPTIONAL IfcTorqueMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadSingleForceWarping
+ SUBTYPE OF (IfcStructuralLoadSingleForce);
+	WarpingMoment : OPTIONAL IfcWarpingMomentMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralLoadStatic
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralLoadLinearForce
+	,IfcStructuralLoadPlanarForce
+	,IfcStructuralLoadSingleDisplacement
+	,IfcStructuralLoadSingleForce
+	,IfcStructuralLoadTemperature))
+ SUBTYPE OF (IfcStructuralLoad);
+END_ENTITY;
+
+ENTITY IfcStructuralLoadTemperature
+ SUBTYPE OF (IfcStructuralLoadStatic);
+	DeltaT_Constant : OPTIONAL IfcThermodynamicTemperatureMeasure;
+	DeltaT_Y : OPTIONAL IfcThermodynamicTemperatureMeasure;
+	DeltaT_Z : OPTIONAL IfcThermodynamicTemperatureMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralMember
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralCurveMember
+	,IfcStructuralSurfaceMember))
+ SUBTYPE OF (IfcStructuralItem);
+ INVERSE
+	ReferencesElement : SET [0:?] OF IfcRelConnectsStructuralElement FOR RelatedStructuralMember;
+	ConnectedBy : SET [0:?] OF IfcRelConnectsStructuralMember FOR RelatingStructuralMember;
+END_ENTITY;
+
+ENTITY IfcStructuralPlanarAction
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralPlanarActionVarying))
+ SUBTYPE OF (IfcStructuralAction);
+	ProjectedOrTrue : IfcProjectedOrTrueLengthEnum;
+ WHERE
+	WR61 : SIZEOF(['IFC2X3.IFCSTRUCTURALLOADPLANARFORCE',
+                     'IFC2X3.IFCSTRUCTURALLOADTEMPERATURE']
+             * TYPEOF(SELF\IfcStructuralActivity.AppliedLoad)) = 1;
+END_ENTITY;
+
+ENTITY IfcStructuralPlanarActionVarying
+ SUBTYPE OF (IfcStructuralPlanarAction);
+	VaryingAppliedLoadLocation : IfcShapeAspect;
+	SubsequentAppliedLoads : LIST [2:?] OF IfcStructuralLoad;
+ DERIVE
+	VaryingAppliedLoads : LIST [3:?] OF IfcStructuralLoad := IfcAddToBeginOfList(SELF\IfcStructuralActivity.AppliedLoad, SubsequentAppliedLoads);
+END_ENTITY;
+
+ENTITY IfcStructuralPointAction
+ SUBTYPE OF (IfcStructuralAction);
+ WHERE
+	WR61 : SIZEOF(['IFC2X3.IFCSTRUCTURALLOADSINGLEFORCE',
+                     'IFC2X3.IFCSTRUCTURALLOADSINGLEDISPLACEMENT']
+             * TYPEOF(SELF\IfcStructuralActivity.AppliedLoad)) = 1;
+END_ENTITY;
+
+ENTITY IfcStructuralPointConnection
+ SUBTYPE OF (IfcStructuralConnection);
+END_ENTITY;
+
+ENTITY IfcStructuralPointReaction
+ SUBTYPE OF (IfcStructuralReaction);
+ WHERE
+	WR61 : SIZEOF(['IFC2X3.IFCSTRUCTURALLOADSINGLEFORCE',
+                     'IFC2X3.IFCSTRUCTURALLOADSINGLEDISPLACEMENT']
+             * TYPEOF(SELF\IfcStructuralActivity.AppliedLoad)) = 1;
+END_ENTITY;
+
+ENTITY IfcStructuralProfileProperties
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralSteelProfileProperties))
+ SUBTYPE OF (IfcGeneralProfileProperties);
+	TorsionalConstantX : OPTIONAL IfcMomentOfInertiaMeasure;
+	MomentOfInertiaYZ : OPTIONAL IfcMomentOfInertiaMeasure;
+	MomentOfInertiaY : OPTIONAL IfcMomentOfInertiaMeasure;
+	MomentOfInertiaZ : OPTIONAL IfcMomentOfInertiaMeasure;
+	WarpingConstant : OPTIONAL IfcWarpingConstantMeasure;
+	ShearCentreZ : OPTIONAL IfcLengthMeasure;
+	ShearCentreY : OPTIONAL IfcLengthMeasure;
+	ShearDeformationAreaZ : OPTIONAL IfcAreaMeasure;
+	ShearDeformationAreaY : OPTIONAL IfcAreaMeasure;
+	MaximumSectionModulusY : OPTIONAL IfcSectionModulusMeasure;
+	MinimumSectionModulusY : OPTIONAL IfcSectionModulusMeasure;
+	MaximumSectionModulusZ : OPTIONAL IfcSectionModulusMeasure;
+	MinimumSectionModulusZ : OPTIONAL IfcSectionModulusMeasure;
+	TorsionalSectionModulus : OPTIONAL IfcSectionModulusMeasure;
+	CentreOfGravityInX : OPTIONAL IfcLengthMeasure;
+	CentreOfGravityInY : OPTIONAL IfcLengthMeasure;
+ WHERE
+	WR21 : NOT(EXISTS(ShearDeformationAreaY)) OR (ShearDeformationAreaY >= 0.);
+	WR22 : NOT(EXISTS(ShearDeformationAreaZ)) OR (ShearDeformationAreaZ >= 0.);
+END_ENTITY;
+
+ENTITY IfcStructuralReaction
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStructuralPointReaction))
+ SUBTYPE OF (IfcStructuralActivity);
+ INVERSE
+	Causes : SET [0:?] OF IfcStructuralAction FOR CausedBy;
+END_ENTITY;
+
+ENTITY IfcStructuralResultGroup
+ SUBTYPE OF (IfcGroup);
+	TheoryType : IfcAnalysisTheoryTypeEnum;
+	ResultForLoadGroup : OPTIONAL IfcStructuralLoadGroup;
+	IsLinear : BOOLEAN;
+ INVERSE
+	ResultGroupFor : SET [0:1] OF IfcStructuralAnalysisModel FOR HasResults;
+END_ENTITY;
+
+ENTITY IfcStructuralSteelProfileProperties
+ SUBTYPE OF (IfcStructuralProfileProperties);
+	ShearAreaZ : OPTIONAL IfcAreaMeasure;
+	ShearAreaY : OPTIONAL IfcAreaMeasure;
+	PlasticShapeFactorY : OPTIONAL IfcPositiveRatioMeasure;
+	PlasticShapeFactorZ : OPTIONAL IfcPositiveRatioMeasure;
+ WHERE
+	WR31 : NOT(EXISTS(ShearAreaY)) OR (ShearAreaY >= 0.);
+	WR32 : NOT(EXISTS(ShearAreaZ)) OR (ShearAreaZ >= 0.);
+END_ENTITY;
+
+ENTITY IfcStructuralSurfaceConnection
+ SUBTYPE OF (IfcStructuralConnection);
+END_ENTITY;
+
+ENTITY IfcStructuralSurfaceMember
+ SUPERTYPE OF (ONEOF
+	(IfcStructuralSurfaceMemberVarying))
+ SUBTYPE OF (IfcStructuralMember);
+	PredefinedType : IfcStructuralSurfaceTypeEnum;
+	Thickness : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcStructuralSurfaceMemberVarying
+ SUBTYPE OF (IfcStructuralSurfaceMember);
+	SubsequentThickness : LIST [2:?] OF IfcPositiveLengthMeasure;
+	VaryingThicknessLocation : IfcShapeAspect;
+ DERIVE
+	VaryingThickness : LIST [3:?] OF IfcPositiveLengthMeasure := IfcAddToBeginOfList(SELF\IfcStructuralSurfaceMember.Thickness, SubsequentThickness);
+ WHERE
+	WR61 : EXISTS(SELF\IfcStructuralSurfaceMember.Thickness);
+	WR62 : SIZEOF(QUERY(temp <* SELF.VaryingThicknessLocation.ShapeRepresentations |
+               NOT(SIZEOF(temp\IfcRepresentation.Items) = 1)
+               )) = 0;
+	WR63 : SIZEOF(QUERY(temp <* SELF.VaryingThicknessLocation.ShapeRepresentations |
+               NOT(('IFC2X3.IFCCARTESIANPOINT' IN TYPEOF(temp\IfcRepresentation.Items[1]))
+                     OR
+                   ('IFC2X3.IFCPOINTONSURFACE' IN TYPEOF(temp\IfcRepresentation.Items[1])))
+               )) = 0;
+END_ENTITY;
+
+ENTITY IfcStructuredDimensionCallout
+ SUBTYPE OF (IfcDraughtingCallout);
+ WHERE
+	WR31 : SIZEOF(QUERY ( Ato <* QUERY ( Con <* SELF.contents | (
+                   'IFC2X3.IFCANNOTATIONTEXTOCCURRENCE' IN 
+                    TYPEOF(Con)) ) | (NOT (Ato.Name IN ['dimension value',
+                   'tolerance value','unit text','prefix text','suffix text']))))
+                  = 0;
+END_ENTITY;
+
+ENTITY IfcStyleModel
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcStyledRepresentation))
+ SUBTYPE OF (IfcRepresentation);
+END_ENTITY;
+
+ENTITY IfcStyledItem
+ SUPERTYPE OF (ONEOF
+	(IfcAnnotationOccurrence))
+ SUBTYPE OF (IfcRepresentationItem);
+	Item : OPTIONAL IfcRepresentationItem;
+	Styles : SET [1:?] OF IfcPresentationStyleAssignment;
+	Name : OPTIONAL IfcLabel;
+ WHERE
+	WR11 : SIZEOF(Styles) = 1;
+	WR12 : NOT('IFC2X3.IFCSTYLEDITEM' IN TYPEOF(Item));
+END_ENTITY;
+
+ENTITY IfcStyledRepresentation
+ SUBTYPE OF (IfcStyleModel);
+ WHERE
+	WR21 : SIZEOF(QUERY(temp <* SELF\IfcRepresentation.Items | 
+               (NOT('IFC2X3.IFCSTYLEDITEM' IN TYPEOF(temp)))
+             )) = 0;
+END_ENTITY;
+
+ENTITY IfcSubContractResource
+ SUBTYPE OF (IfcConstructionResource);
+	SubContractor : OPTIONAL IfcActorSelect;
+	JobDescription : OPTIONAL IfcText;
+END_ENTITY;
+
+ENTITY IfcSubedge
+ SUBTYPE OF (IfcEdge);
+	ParentEdge : IfcEdge;
+END_ENTITY;
+
+ENTITY IfcSurface
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBoundedSurface
+	,IfcElementarySurface
+	,IfcSweptSurface))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+END_ENTITY;
+
+ENTITY IfcSurfaceCurveSweptAreaSolid
+ SUBTYPE OF (IfcSweptAreaSolid);
+	Directrix : IfcCurve;
+	StartParam : IfcParameterValue;
+	EndParam : IfcParameterValue;
+	ReferenceSurface : IfcSurface;
+END_ENTITY;
+
+ENTITY IfcSurfaceOfLinearExtrusion
+ SUBTYPE OF (IfcSweptSurface);
+	ExtrudedDirection : IfcDirection;
+	Depth : IfcLengthMeasure;
+ DERIVE
+	ExtrusionAxis : IfcVector := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector (ExtrudedDirection, Depth);
+ WHERE
+	WR41 : Depth > 0.;
+END_ENTITY;
+
+ENTITY IfcSurfaceOfRevolution
+ SUBTYPE OF (IfcSweptSurface);
+	AxisPosition : IfcAxis1Placement;
+ DERIVE
+	AxisLine : IfcLine := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcCurve() || IfcLine(AxisPosition.Location, 
+                       IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector(AxisPosition.Z,1.0));
+END_ENTITY;
+
+ENTITY IfcSurfaceStyle
+ SUBTYPE OF (IfcPresentationStyle);
+	Side : IfcSurfaceSide;
+	Styles : SET [1:5] OF IfcSurfaceStyleElementSelect;
+ WHERE
+	WR11 : SIZEOF(QUERY(Style <* SELF.Styles |
+               'IFC2X3.IFCSURFACESTYLESHADING' IN
+                TYPEOF(Style)
+               )) <= 1;
+	WR12 : SIZEOF(QUERY(Style <* SELF.Styles |
+               'IFC2X3.IFCSURFACESTYLELIGHTING' IN
+                TYPEOF(Style)
+               )) <= 1;
+	WR13 : SIZEOF(QUERY(Style <* SELF.Styles |
+               'IFC2X3.IFCSURFACESTYLEREFRACTION' IN
+                TYPEOF(Style)
+               )) <= 1;
+	WR14 : SIZEOF(QUERY(Style <* SELF.Styles |
+               'IFC2X3.IFCSURFACESTYLEWITHTEXTURES' IN
+                TYPEOF(Style)
+               )) <= 1;
+	WR15 : SIZEOF(QUERY(Style <* SELF.Styles |
+               'IFC2X3.IFCEXTERNALLYDEFINEDSURFACESTYLE' IN
+                TYPEOF(Style)
+               )) <= 1;
+END_ENTITY;
+
+ENTITY IfcSurfaceStyleLighting;
+	DiffuseTransmissionColour : IfcColourRgb;
+	DiffuseReflectionColour : IfcColourRgb;
+	TransmissionColour : IfcColourRgb;
+	ReflectanceColour : IfcColourRgb;
+END_ENTITY;
+
+ENTITY IfcSurfaceStyleRefraction;
+	RefractionIndex : OPTIONAL IfcReal;
+	DispersionFactor : OPTIONAL IfcReal;
+END_ENTITY;
+
+ENTITY IfcSurfaceStyleRendering
+ SUBTYPE OF (IfcSurfaceStyleShading);
+	Transparency : OPTIONAL IfcNormalisedRatioMeasure;
+	DiffuseColour : OPTIONAL IfcColourOrFactor;
+	TransmissionColour : OPTIONAL IfcColourOrFactor;
+	DiffuseTransmissionColour : OPTIONAL IfcColourOrFactor;
+	ReflectionColour : OPTIONAL IfcColourOrFactor;
+	SpecularColour : OPTIONAL IfcColourOrFactor;
+	SpecularHighlight : OPTIONAL IfcSpecularHighlightSelect;
+	ReflectanceMethod : IfcReflectanceMethodEnum;
+END_ENTITY;
+
+ENTITY IfcSurfaceStyleShading
+ SUPERTYPE OF (ONEOF
+	(IfcSurfaceStyleRendering));
+	SurfaceColour : IfcColourRgb;
+END_ENTITY;
+
+ENTITY IfcSurfaceStyleWithTextures;
+	Textures : LIST [1:?] OF IfcSurfaceTexture;
+END_ENTITY;
+
+ENTITY IfcSurfaceTexture
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcBlobTexture
+	,IfcImageTexture
+	,IfcPixelTexture));
+	RepeatS : BOOLEAN;
+	RepeatT : BOOLEAN;
+	TextureType : IfcSurfaceTextureEnum;
+	TextureTransform : OPTIONAL IfcCartesianTransformationOperator2D;
+END_ENTITY;
+
+ENTITY IfcSweptAreaSolid
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcExtrudedAreaSolid
+	,IfcRevolvedAreaSolid
+	,IfcSurfaceCurveSweptAreaSolid))
+ SUBTYPE OF (IfcSolidModel);
+	SweptArea : IfcProfileDef;
+	Position : IfcAxis2Placement3D;
+ WHERE
+	WR22 : SweptArea.ProfileType = IfcProfileTypeEnum.Area;
+END_ENTITY;
+
+ENTITY IfcSweptDiskSolid
+ SUBTYPE OF (IfcSolidModel);
+	Directrix : IfcCurve;
+	Radius : IfcPositiveLengthMeasure;
+	InnerRadius : OPTIONAL IfcPositiveLengthMeasure;
+	StartParam : IfcParameterValue;
+	EndParam : IfcParameterValue;
+ WHERE
+	WR1 : Directrix.Dim = 3;
+	WR2 : (NOT EXISTS(InnerRadius)) OR (Radius > InnerRadius);
+END_ENTITY;
+
+ENTITY IfcSweptSurface
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcSurfaceOfLinearExtrusion
+	,IfcSurfaceOfRevolution))
+ SUBTYPE OF (IfcSurface);
+	SweptCurve : IfcProfileDef;
+	Position : IfcAxis2Placement3D;
+ DERIVE
+	Dim : IfcDimensionCount := Position.Dim;
+ WHERE
+	WR1 : NOT('IFC2X3.IFCDERIVEDPROFILEDEF' IN TYPEOF(SweptCurve));
+	WR2 : SweptCurve.ProfileType = IfcProfileTypeEnum.Curve;
+END_ENTITY;
+
+ENTITY IfcSwitchingDeviceType
+ SUBTYPE OF (IfcFlowControllerType);
+	PredefinedType : IfcSwitchingDeviceTypeEnum;
+END_ENTITY;
+
+ENTITY IfcSymbolStyle
+ SUBTYPE OF (IfcPresentationStyle);
+	StyleOfSymbol : IfcSymbolStyleSelect;
+END_ENTITY;
+
+ENTITY IfcSystem
+ SUPERTYPE OF (ONEOF
+	(IfcElectricalCircuit
+	,IfcStructuralAnalysisModel))
+ SUBTYPE OF (IfcGroup);
+ INVERSE
+	ServicesBuildings : SET [0:1] OF IfcRelServicesBuildings FOR RelatingSystem;
+END_ENTITY;
+
+ENTITY IfcSystemFurnitureElementType
+ SUBTYPE OF (IfcFurnishingElementType);
+END_ENTITY;
+
+ENTITY IfcTShapeProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	Depth : IfcPositiveLengthMeasure;
+	FlangeWidth : IfcPositiveLengthMeasure;
+	WebThickness : IfcPositiveLengthMeasure;
+	FlangeThickness : IfcPositiveLengthMeasure;
+	FilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+	FlangeEdgeRadius : OPTIONAL IfcPositiveLengthMeasure;
+	WebEdgeRadius : OPTIONAL IfcPositiveLengthMeasure;
+	WebSlope : OPTIONAL IfcPlaneAngleMeasure;
+	FlangeSlope : OPTIONAL IfcPlaneAngleMeasure;
+	CentreOfGravityInY : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR1 : FlangeThickness < Depth;
+	WR2 : WebThickness < FlangeWidth;
+END_ENTITY;
+
+ENTITY IfcTable;
+	Name : STRING;
+	Rows : LIST [1:?] OF IfcTableRow;
+ DERIVE
+	NumberOfCellsInRow : INTEGER := HIINDEX(Rows[1].RowCells);
+	NumberOfHeadings : INTEGER := SIZEOF(QUERY( Temp <* Rows | Temp.IsHeading));
+	NumberOfDataRows : INTEGER := SIZEOF(QUERY( Temp <* Rows | NOT(Temp.IsHeading)));
+ WHERE
+	WR1 : SIZEOF(QUERY( Temp <* Rows | HIINDEX(Temp.RowCells) <> HIINDEX(Rows[1].RowCells))) = 0;
+	WR2 : SIZEOF(QUERY( Temp <* Rows | HIINDEX(Temp.RowCells) <> HIINDEX(Rows[1].RowCells))) = 0;
+	WR3 : { 0 <= NumberOfHeadings <= 1 };
+END_ENTITY;
+
+ENTITY IfcTableRow;
+	RowCells : LIST [1:?] OF IfcValue;
+	IsHeading : BOOLEAN;
+ INVERSE
+	OfTable : IfcTable FOR Rows;
+END_ENTITY;
+
+ENTITY IfcTankType
+ SUBTYPE OF (IfcFlowStorageDeviceType);
+	PredefinedType : IfcTankTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcTankTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcTankTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcTask
+ SUPERTYPE OF (ONEOF
+	(IfcMove
+	,IfcOrderAction))
+ SUBTYPE OF (IfcProcess);
+	TaskId : IfcIdentifier;
+	Status : OPTIONAL IfcLabel;
+	WorkMethod : OPTIONAL IfcLabel;
+	IsMilestone : BOOLEAN;
+	Priority : OPTIONAL INTEGER;
+ WHERE
+	WR1 : SIZEOF(QUERY(temp <* SELF\IfcObjectDefinition.Decomposes | NOT('IFC2X3.IFCRELNESTS' IN TYPEOF(temp)))) = 0;
+	WR2 : SIZEOF(QUERY(temp <* SELF\IfcObjectDefinition.IsDecomposedBy | NOT('IFC2X3.IFCRELNESTS' IN TYPEOF(temp)))) = 0;
+	WR3 : EXISTS(SELF\IfcRoot.Name);
+END_ENTITY;
+
+ENTITY IfcTelecomAddress
+ SUBTYPE OF (IfcAddress);
+	TelephoneNumbers : OPTIONAL LIST [1:?] OF IfcLabel;
+	FacsimileNumbers : OPTIONAL LIST [1:?] OF IfcLabel;
+	PagerNumber : OPTIONAL IfcLabel;
+	ElectronicMailAddresses : OPTIONAL LIST [1:?] OF IfcLabel;
+	WWWHomePageURL : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : EXISTS (TelephoneNumbers) OR
+            EXISTS (PagerNumber) OR
+            EXISTS (FacsimileNumbers) OR 
+            EXISTS (ElectronicMailAddresses) OR 
+            EXISTS (WWWHomePageURL);
+END_ENTITY;
+
+ENTITY IfcTendon
+ SUBTYPE OF (IfcReinforcingElement);
+	PredefinedType : IfcTendonTypeEnum;
+	NominalDiameter : IfcPositiveLengthMeasure;
+	CrossSectionArea : IfcAreaMeasure;
+	TensionForce : OPTIONAL IfcForceMeasure;
+	PreStress : OPTIONAL IfcPressureMeasure;
+	FrictionCoefficient : OPTIONAL IfcNormalisedRatioMeasure;
+	AnchorageSlip : OPTIONAL IfcPositiveLengthMeasure;
+	MinCurvatureRadius : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR1 : (PredefinedType <> IfcTendonTypeEnum.USERDEFINED) OR ((PredefinedType = IfcTendonTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcObject.ObjectType));
+END_ENTITY;
+
+ENTITY IfcTendonAnchor
+ SUBTYPE OF (IfcReinforcingElement);
+END_ENTITY;
+
+ENTITY IfcTerminatorSymbol
+ SUPERTYPE OF (ONEOF
+	(IfcDimensionCurveTerminator))
+ SUBTYPE OF (IfcAnnotationSymbolOccurrence);
+	AnnotatedCurve : IfcAnnotationCurveOccurrence;
+END_ENTITY;
+
+ENTITY IfcTextLiteral
+ SUPERTYPE OF (ONEOF
+	(IfcTextLiteralWithExtent))
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Literal : IfcPresentableText;
+	Placement : IfcAxis2Placement;
+	Path : IfcTextPath;
+END_ENTITY;
+
+ENTITY IfcTextLiteralWithExtent
+ SUBTYPE OF (IfcTextLiteral);
+	Extent : IfcPlanarExtent;
+	BoxAlignment : IfcBoxAlignment;
+ WHERE
+	WR31 : NOT('IFC2X3.IFCPLANARBOX' IN TYPEOF(Extent));
+END_ENTITY;
+
+ENTITY IfcTextStyle
+ SUBTYPE OF (IfcPresentationStyle);
+	TextCharacterAppearance : OPTIONAL IfcCharacterStyleSelect;
+	TextStyle : OPTIONAL IfcTextStyleSelect;
+	TextFontStyle : IfcTextFontSelect;
+END_ENTITY;
+
+ENTITY IfcTextStyleFontModel
+ SUBTYPE OF (IfcPreDefinedTextFont);
+	FontFamily : OPTIONAL LIST [1:?] OF IfcTextFontName;
+	FontStyle : OPTIONAL IfcFontStyle;
+	FontVariant : OPTIONAL IfcFontVariant;
+	FontWeight : OPTIONAL IfcFontWeight;
+	FontSize : IfcSizeSelect;
+ WHERE
+	WR31 : ('IFC2X3.IFCLENGTHMEASURE' IN TYPEOF(SELF.FontSize)) AND
+             (SELF.FontSize > 0.);
+END_ENTITY;
+
+ENTITY IfcTextStyleForDefinedFont;
+	Colour : IfcColour;
+	BackgroundColour : OPTIONAL IfcColour;
+END_ENTITY;
+
+ENTITY IfcTextStyleTextModel;
+	TextIndent : OPTIONAL IfcSizeSelect;
+	TextAlign : OPTIONAL IfcTextAlignment;
+	TextDecoration : OPTIONAL IfcTextDecoration;
+	LetterSpacing : OPTIONAL IfcSizeSelect;
+	WordSpacing : OPTIONAL IfcSizeSelect;
+	TextTransform : OPTIONAL IfcTextTransformation;
+	LineHeight : OPTIONAL IfcSizeSelect;
+END_ENTITY;
+
+ENTITY IfcTextStyleWithBoxCharacteristics;
+	BoxHeight : OPTIONAL IfcPositiveLengthMeasure;
+	BoxWidth : OPTIONAL IfcPositiveLengthMeasure;
+	BoxSlantAngle : OPTIONAL IfcPlaneAngleMeasure;
+	BoxRotateAngle : OPTIONAL IfcPlaneAngleMeasure;
+	CharacterSpacing : OPTIONAL IfcSizeSelect;
+END_ENTITY;
+
+ENTITY IfcTextureCoordinate
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcTextureCoordinateGenerator
+	,IfcTextureMap));
+ INVERSE
+	AnnotatedSurface : SET [1:1] OF IfcAnnotationSurface FOR TextureCoordinates;
+END_ENTITY;
+
+ENTITY IfcTextureCoordinateGenerator
+ SUBTYPE OF (IfcTextureCoordinate);
+	Mode : IfcLabel;
+	Parameter : LIST [1:?] OF IfcSimpleValue;
+END_ENTITY;
+
+ENTITY IfcTextureMap
+ SUBTYPE OF (IfcTextureCoordinate);
+	TextureMaps : SET [1:?] OF IfcVertexBasedTextureMap;
+ WHERE
+	WR11 : SIZEOF([
+               'IFC2X3.IFCSHELLBASEDSURFACEMODEL',
+               'IFC2X3.IFCFACEBASEDSURFACEMODEL',
+               'IFC2X3.IFCFACETEDBREP',
+               'IFC2X3.IFCFACETEDBREPWITHVOIDS'] 
+              * TYPEOF(SELF\IfcTextureCoordinate.AnnotatedSurface[1].Item)
+               ) >= 1;
+END_ENTITY;
+
+ENTITY IfcTextureVertex;
+	Coordinates : LIST [2:2] OF IfcParameterValue;
+END_ENTITY;
+
+ENTITY IfcThermalMaterialProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	SpecificHeatCapacity : OPTIONAL IfcSpecificHeatCapacityMeasure;
+	BoilingPoint : OPTIONAL IfcThermodynamicTemperatureMeasure;
+	FreezingPoint : OPTIONAL IfcThermodynamicTemperatureMeasure;
+	ThermalConductivity : OPTIONAL IfcThermalConductivityMeasure;
+ UNIQUE
+	UR11 : Material;
+END_ENTITY;
+
+ENTITY IfcTimeSeries
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcIrregularTimeSeries
+	,IfcRegularTimeSeries));
+	Name : IfcLabel;
+	Description : OPTIONAL IfcText;
+	StartTime : IfcDateTimeSelect;
+	EndTime : IfcDateTimeSelect;
+	TimeSeriesDataType : IfcTimeSeriesDataTypeEnum;
+	DataOrigin : IfcDataOriginEnum;
+	UserDefinedDataOrigin : OPTIONAL IfcLabel;
+	Unit : OPTIONAL IfcUnit;
+ INVERSE
+	DocumentedBy : SET [0:1] OF IfcTimeSeriesReferenceRelationship FOR ReferencedTimeSeries;
+END_ENTITY;
+
+ENTITY IfcTimeSeriesReferenceRelationship;
+	ReferencedTimeSeries : IfcTimeSeries;
+	TimeSeriesReferences : SET [1:?] OF IfcDocumentSelect;
+END_ENTITY;
+
+ENTITY IfcTimeSeriesSchedule
+ SUBTYPE OF (IfcControl);
+	ApplicableDates : OPTIONAL LIST [1:?] OF IfcDateTimeSelect;
+	TimeSeriesScheduleType : IfcTimeSeriesScheduleTypeEnum;
+	TimeSeries : IfcTimeSeries;
+ WHERE
+	WR41 : NOT(TimeSeriesScheduleType=IfcTimeSeriesScheduleTypeEnum.USERDEFINED) OR EXISTS(SELF\IfcObject.ObjectType);
+END_ENTITY;
+
+ENTITY IfcTimeSeriesValue;
+	ListValues : LIST [1:?] OF IfcValue;
+END_ENTITY;
+
+ENTITY IfcTopologicalRepresentationItem
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcConnectedFaceSet
+	,IfcEdge
+	,IfcFace
+	,IfcFaceBound
+	,IfcLoop
+	,IfcPath
+	,IfcVertex))
+ SUBTYPE OF (IfcRepresentationItem);
+END_ENTITY;
+
+ENTITY IfcTopologyRepresentation
+ SUBTYPE OF (IfcShapeModel);
+ WHERE
+	WR21 : SIZEOF(QUERY(temp <* SELF\IfcRepresentation.Items | 
+               NOT('IFC2X3.IFCTOPOLOGICALREPRESENTATIONITEM' IN TYPEOF(temp))
+             )) = 0;
+	WR22 : EXISTS(SELF\IfcRepresentation.RepresentationType);
+	WR23 : IfcTopologyRepresentationTypes(SELF\IfcRepresentation.RepresentationType, SELF\IfcRepresentation.Items);
+END_ENTITY;
+
+ENTITY IfcTransformerType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcTransformerTypeEnum;
+END_ENTITY;
+
+ENTITY IfcTransportElement
+ SUBTYPE OF (IfcElement);
+	OperationType : OPTIONAL IfcTransportElementTypeEnum;
+	CapacityByWeight : OPTIONAL IfcMassMeasure;
+	CapacityByNumber : OPTIONAL IfcCountMeasure;
+END_ENTITY;
+
+ENTITY IfcTransportElementType
+ SUBTYPE OF (IfcElementType);
+	PredefinedType : IfcTransportElementTypeEnum;
+END_ENTITY;
+
+ENTITY IfcTrapeziumProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	BottomXDim : IfcPositiveLengthMeasure;
+	TopXDim : IfcPositiveLengthMeasure;
+	YDim : IfcPositiveLengthMeasure;
+	TopXOffset : IfcLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcTrimmedCurve
+ SUBTYPE OF (IfcBoundedCurve);
+	BasisCurve : IfcCurve;
+	Trim1 : SET [1:2] OF IfcTrimmingSelect;
+	Trim2 : SET [1:2] OF IfcTrimmingSelect;
+	SenseAgreement : BOOLEAN;
+	MasterRepresentation : IfcTrimmingPreference;
+ WHERE
+	WR41 : (HIINDEX(Trim1) = 1) OR (TYPEOF(Trim1[1]) <> TYPEOF(Trim1[2]));
+	WR42 : (HIINDEX(Trim2) = 1) OR (TYPEOF(Trim2[1]) <> TYPEOF(Trim2[2]));
+	WR43 : NOT('IFC2X3.IFCBOUNDEDCURVE' IN TYPEOF(BasisCurve));
+END_ENTITY;
+
+ENTITY IfcTubeBundleType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcTubeBundleTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcTubeBundleTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcTubeBundleTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcTwoDirectionRepeatFactor
+ SUBTYPE OF (IfcOneDirectionRepeatFactor);
+	SecondRepeatFactor : IfcVector;
+END_ENTITY;
+
+ENTITY IfcTypeObject
+ SUPERTYPE OF (ONEOF
+	(IfcTypeProduct))
+ SUBTYPE OF (IfcObjectDefinition);
+	ApplicableOccurrence : OPTIONAL IfcLabel;
+	HasPropertySets : OPTIONAL SET [1:?] OF IfcPropertySetDefinition;
+ INVERSE
+	ObjectTypeOf : SET [0:1] OF IfcRelDefinesByType FOR RelatingType;
+ WHERE
+	WR1 : EXISTS(SELF\IfcRoot.Name);
+END_ENTITY;
+
+ENTITY IfcTypeProduct
+ SUPERTYPE OF (ONEOF
+	(IfcDoorStyle
+	,IfcElementType
+	,IfcWindowStyle))
+ SUBTYPE OF (IfcTypeObject);
+	RepresentationMaps : OPTIONAL LIST [1:?] OF UNIQUE IfcRepresentationMap;
+	Tag : OPTIONAL IfcLabel;
+ WHERE
+	WR41 : NOT(EXISTS(SELF\IfcTypeObject.ObjectTypeOf[1])) OR
+             (SIZEOF(QUERY(temp <* SELF\IfcTypeObject.ObjectTypeOf[1].RelatedObjects |
+               NOT('IFC2X3.IFCPRODUCT' IN TYPEOF(temp)))
+             ) = 0);
+END_ENTITY;
+
+ENTITY IfcUShapeProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	Depth : IfcPositiveLengthMeasure;
+	FlangeWidth : IfcPositiveLengthMeasure;
+	WebThickness : IfcPositiveLengthMeasure;
+	FlangeThickness : IfcPositiveLengthMeasure;
+	FilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+	EdgeRadius : OPTIONAL IfcPositiveLengthMeasure;
+	FlangeSlope : OPTIONAL IfcPlaneAngleMeasure;
+	CentreOfGravityInX : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR21 : FlangeThickness < (Depth / 2.);
+	WR22 : WebThickness < FlangeWidth;
+END_ENTITY;
+
+ENTITY IfcUnitAssignment;
+	Units : SET [1:?] OF IfcUnit;
+ WHERE
+	WR01 : IfcCorrectUnitAssignment(Units);
+END_ENTITY;
+
+ENTITY IfcUnitaryEquipmentType
+ SUBTYPE OF (IfcEnergyConversionDeviceType);
+	PredefinedType : IfcUnitaryEquipmentTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcUnitaryEquipmentTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcUnitaryEquipmentTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcValveType
+ SUBTYPE OF (IfcFlowControllerType);
+	PredefinedType : IfcValveTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcValveTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcValveTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcVector
+ SUBTYPE OF (IfcGeometricRepresentationItem);
+	Orientation : IfcDirection;
+	Magnitude : IfcLengthMeasure;
+ DERIVE
+	Dim : IfcDimensionCount := Orientation.Dim;
+ WHERE
+	WR1 : Magnitude >= 0.0;
+END_ENTITY;
+
+ENTITY IfcVertex
+ SUPERTYPE OF (ONEOF
+	(IfcVertexPoint))
+ SUBTYPE OF (IfcTopologicalRepresentationItem);
+END_ENTITY;
+
+ENTITY IfcVertexBasedTextureMap;
+	TextureVertices : LIST [3:?] OF IfcTextureVertex;
+	TexturePoints : LIST [3:?] OF IfcCartesianPoint;
+END_ENTITY;
+
+ENTITY IfcVertexLoop
+ SUBTYPE OF (IfcLoop);
+	LoopVertex : IfcVertex;
+END_ENTITY;
+
+ENTITY IfcVertexPoint
+ SUBTYPE OF (IfcVertex);
+	VertexGeometry : IfcPoint;
+END_ENTITY;
+
+ENTITY IfcVibrationIsolatorType
+ SUBTYPE OF (IfcDiscreteAccessoryType);
+	PredefinedType : IfcVibrationIsolatorTypeEnum;
+ WHERE
+	WR1 : (PredefinedType <> IfcVibrationIsolatorTypeEnum.USERDEFINED) OR
+            ((PredefinedType = IfcVibrationIsolatorTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcElementType.ElementType));
+END_ENTITY;
+
+ENTITY IfcVirtualElement
+ SUBTYPE OF (IfcElement);
+END_ENTITY;
+
+ENTITY IfcVirtualGridIntersection;
+	IntersectingAxes : LIST [2:2] OF UNIQUE IfcGridAxis;
+	OffsetDistances : LIST [2:3] OF IfcLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcWall
+ SUPERTYPE OF (ONEOF
+	(IfcWallStandardCase))
+ SUBTYPE OF (IfcBuildingElement);
+ WHERE
+	WR1 : SIZEOF (QUERY(temp <* SELF\IfcObjectDefinition.HasAssociations |
+              'IFC2X3.IFCRELASSOCIATESMATERIAL' IN TYPEOF(temp)
+              )) <= 1;
+END_ENTITY;
+
+ENTITY IfcWallStandardCase
+ SUBTYPE OF (IfcWall);
+ WHERE
+	WR1 : SIZEOF (QUERY(temp <* USEDIN(SELF, 'IFC2X3.IFCRELASSOCIATES.RELATEDOBJECTS') |
+                          ('IFC2X3.IFCRELASSOCIATESMATERIAL' IN TYPEOF(temp)) AND
+                          ('IFC2X3.IFCMATERIALLAYERSETUSAGE' IN TYPEOF(temp.RelatingMaterial))
+                          )) = 1;
+END_ENTITY;
+
+ENTITY IfcWallType
+ SUBTYPE OF (IfcBuildingElementType);
+	PredefinedType : IfcWallTypeEnum;
+END_ENTITY;
+
+ENTITY IfcWasteTerminalType
+ SUBTYPE OF (IfcFlowTerminalType);
+	PredefinedType : IfcWasteTerminalTypeEnum;
+END_ENTITY;
+
+ENTITY IfcWaterProperties
+ SUBTYPE OF (IfcMaterialProperties);
+	IsPotable : OPTIONAL BOOLEAN;
+	Hardness : OPTIONAL IfcIonConcentrationMeasure;
+	AlkalinityConcentration : OPTIONAL IfcIonConcentrationMeasure;
+	AcidityConcentration : OPTIONAL IfcIonConcentrationMeasure;
+	ImpuritiesContent : OPTIONAL IfcNormalisedRatioMeasure;
+	PHLevel : OPTIONAL IfcPHMeasure;
+	DissolvedSolidsContent : OPTIONAL IfcNormalisedRatioMeasure;
+ UNIQUE
+	UR11 : Material;
+END_ENTITY;
+
+ENTITY IfcWindow
+ SUBTYPE OF (IfcBuildingElement);
+	OverallHeight : OPTIONAL IfcPositiveLengthMeasure;
+	OverallWidth : OPTIONAL IfcPositiveLengthMeasure;
+END_ENTITY;
+
+ENTITY IfcWindowLiningProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	LiningDepth : OPTIONAL IfcPositiveLengthMeasure;
+	LiningThickness : OPTIONAL IfcPositiveLengthMeasure;
+	TransomThickness : OPTIONAL IfcPositiveLengthMeasure;
+	MullionThickness : OPTIONAL IfcPositiveLengthMeasure;
+	FirstTransomOffset : OPTIONAL IfcNormalisedRatioMeasure;
+	SecondTransomOffset : OPTIONAL IfcNormalisedRatioMeasure;
+	FirstMullionOffset : OPTIONAL IfcNormalisedRatioMeasure;
+	SecondMullionOffset : OPTIONAL IfcNormalisedRatioMeasure;
+	ShapeAspectStyle : OPTIONAL IfcShapeAspect;
+ WHERE
+	WR31 : NOT(NOT(EXISTS(LiningDepth)) AND EXISTS(LiningThickness));
+	WR32 : NOT(NOT(EXISTS(FirstTransomOffset)) AND EXISTS(SecondTransomOffset));
+	WR33 : NOT(NOT(EXISTS(FirstMullionOffset)) AND EXISTS(SecondMullionOffset));
+	WR34 : EXISTS(SELF\IfcPropertySetDefinition.DefinesType[1]) AND 
+             ('IFC2X3.IFCWINDOWSTYLE' IN TYPEOF(SELF\IfcPropertySetDefinition.DefinesType[1]));
+END_ENTITY;
+
+ENTITY IfcWindowPanelProperties
+ SUBTYPE OF (IfcPropertySetDefinition);
+	OperationType : IfcWindowPanelOperationEnum;
+	PanelPosition : IfcWindowPanelPositionEnum;
+	FrameDepth : OPTIONAL IfcPositiveLengthMeasure;
+	FrameThickness : OPTIONAL IfcPositiveLengthMeasure;
+	ShapeAspectStyle : OPTIONAL IfcShapeAspect;
+END_ENTITY;
+
+ENTITY IfcWindowStyle
+ SUBTYPE OF (IfcTypeProduct);
+	ConstructionType : IfcWindowStyleConstructionEnum;
+	OperationType : IfcWindowStyleOperationEnum;
+	ParameterTakesPrecedence : BOOLEAN;
+	Sizeable : BOOLEAN;
+END_ENTITY;
+
+ENTITY IfcWorkControl
+ ABSTRACT SUPERTYPE OF (ONEOF
+	(IfcWorkPlan
+	,IfcWorkSchedule))
+ SUBTYPE OF (IfcControl);
+	Identifier : IfcIdentifier;
+	CreationDate : IfcDateTimeSelect;
+	Creators : OPTIONAL SET [1:?] OF IfcPerson;
+	Purpose : OPTIONAL IfcLabel;
+	Duration : OPTIONAL IfcTimeMeasure;
+	TotalFloat : OPTIONAL IfcTimeMeasure;
+	StartTime : IfcDateTimeSelect;
+	FinishTime : OPTIONAL IfcDateTimeSelect;
+	WorkControlType : OPTIONAL IfcWorkControlTypeEnum;
+	UserDefinedControlType : OPTIONAL IfcLabel;
+ WHERE
+	WR1 : (WorkControlType <> IfcWorkControlTypeEnum.USERDEFINED) OR
+            ((WorkControlType = IfcWorkControlTypeEnum.USERDEFINED) AND EXISTS(SELF\IfcWorkControl.UserDefinedControlType));
+END_ENTITY;
+
+ENTITY IfcWorkPlan
+ SUBTYPE OF (IfcWorkControl);
+END_ENTITY;
+
+ENTITY IfcWorkSchedule
+ SUBTYPE OF (IfcWorkControl);
+END_ENTITY;
+
+ENTITY IfcZShapeProfileDef
+ SUBTYPE OF (IfcParameterizedProfileDef);
+	Depth : IfcPositiveLengthMeasure;
+	FlangeWidth : IfcPositiveLengthMeasure;
+	WebThickness : IfcPositiveLengthMeasure;
+	FlangeThickness : IfcPositiveLengthMeasure;
+	FilletRadius : OPTIONAL IfcPositiveLengthMeasure;
+	EdgeRadius : OPTIONAL IfcPositiveLengthMeasure;
+ WHERE
+	WR21 : FlangeThickness < (Depth / 2.);
+END_ENTITY;
+
+ENTITY IfcZone
+ SUBTYPE OF (IfcGroup);
+ WHERE
+	WR1 : SIZEOF (QUERY (temp <* SELF\IfcGroup.IsGroupedBy.RelatedObjects |  NOT(('IFC2X3.IFCZONE' IN TYPEOF(temp)) OR ('IFC2X3.IFCSPACE' IN TYPEOF(temp))) )) = 0;
+END_ENTITY;
+
+FUNCTION IfcAddToBeginOfList
+	(AScalar : GENERIC;
+       AList   : LIST OF GENERIC:AL)
+	: LIST[1:?] OF GENERIC:AL;
+    
+      LOCAL
+        Result : LIST OF GENERIC:AL := [];
+      END_LOCAL;
+  
+    IF NOT(EXISTS(AScalar)) THEN
+      Result := AList;
+    ELSE
+      Result := Result + AScalar;
+      IF (HIINDEX(AList) >= 1) THEN
+        REPEAT i:=1 TO HIINDEX(AList);
+          Result[i+1] := AList[i];
+        END_REPEAT;
+      END_IF;
+    END_IF;
+    RETURN(Result);
+END_FUNCTION;
+
+FUNCTION IfcBaseAxis
+	(Dim : INTEGER; 
+     Axis1, Axis2, Axis3 : IfcDirection)
+	: LIST [2:3] OF IfcDirection;
+  
+  LOCAL
+    U : LIST [2:3] OF IfcDirection;
+    Factor : REAL;
+    D1, D2 : IfcDirection;
+  END_LOCAL;
+  
+    IF (Dim = 3) THEN 
+      D1 := NVL(IfcNormalise(Axis3), IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0,0.0,1.0]));
+      D2 := IfcFirstProjAxis(D1, Axis1);
+      U  := [D2, IfcSecondProjAxis(D1, D2, Axis2), D1];
+    ELSE
+      IF EXISTS(Axis1) THEN
+        D1 := IfcNormalise(Axis1);
+        U  := [D1, IfcOrthogonalComplement(D1)];
+        IF EXISTS(Axis2) THEN
+          Factor := IfcDotProduct(Axis2, U[2]);
+          IF (Factor < 0.0) THEN
+            U[2].DirectionRatios[1] := -U[2].DirectionRatios[1];
+            U[2].DirectionRatios[2] := -U[2].DirectionRatios[2];
+          END_IF;
+        END_IF;
+      ELSE
+        IF EXISTS(Axis2) THEN
+          D1 := IfcNormalise(Axis2);
+          U  := [IfcOrthogonalComplement(D1), D1];
+          U[1].DirectionRatios[1] := -U[1].DirectionRatios[1];
+          U[1].DirectionRatios[2] := -U[1].DirectionRatios[2];
+          ELSE
+            U := [IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([1.0, 0.0]), 
+                  IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0, 1.0])];
+        END_IF;
+      END_IF;
+    END_IF;
+    RETURN(U);
+END_FUNCTION;
+
+FUNCTION IfcBooleanChoose
+	(B : BOOLEAN ;
+       Choice1, Choice2 : Generic : Item)
+	: Generic : Item;
+    IF B THEN
+       RETURN (Choice1);
+    ELSE
+       RETURN (Choice2);
+    END_IF;
+END_FUNCTION;
+
+FUNCTION IfcBuild2Axes
+	(RefDirection : IfcDirection)
+	: LIST [2:2] OF IfcDirection;
+  LOCAL
+    D : IfcDirection := NVL(IfcNormalise(RefDirection),
+        IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([1.0,0.0]));
+  END_LOCAL;
+    RETURN([D, IfcOrthogonalComplement(D)]);
+END_FUNCTION;
+
+FUNCTION IfcBuildAxes
+	(Axis, RefDirection : IfcDirection)
+	: LIST [3:3] OF IfcDirection;
+  LOCAL
+    D1, D2 : IfcDirection;
+  END_LOCAL;
+    D1 := NVL(IfcNormalise(Axis), IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0,0.0,1.0]));
+    D2 := IfcFirstProjAxis(D1, RefDirection);
+    RETURN ([D2, IfcNormalise(IfcCrossProduct(D1,D2)).Orientation, D1]);
+END_FUNCTION;
+
+FUNCTION IfcCorrectDimensions
+	(m   : IfcUnitEnum; Dim : IfcDimensionalExponents)
+	: LOGICAL;  
+  CASE m OF
+    LENGTHUNIT : IF
+      Dim = (IfcDimensionalExponents (1, 0, 0, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    MASSUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 1, 0, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    TIMEUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 1, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ELECTRICCURRENTUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 0, 1, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    THERMODYNAMICTEMPERATUREUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 0, 0, 1, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    AMOUNTOFSUBSTANCEUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 0, 0, 0, 1, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    LUMINOUSINTENSITYUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 0, 0, 0, 0, 1))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    PLANEANGLEUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 0, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    SOLIDANGLEUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 0, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    AREAUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 0, 0, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    VOLUMEUNIT : IF
+      Dim = (IfcDimensionalExponents (3, 0, 0, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+  
+    ABSORBEDDOSEUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 0, -2, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    RADIOACTIVITYUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, -1, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ELECTRICCAPACITANCEUNIT : IF
+      Dim = (IfcDimensionalExponents (-2, 1, 4, 1, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    DOSEEQUIVALENTUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 0, -2, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ELECTRICCHARGEUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 1, 1, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ELECTRICCONDUCTANCEUNIT : IF
+      Dim = (IfcDimensionalExponents (-2, -1, 3, 2, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ELECTRICVOLTAGEUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 1, -3, -1, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ELECTRICRESISTANCEUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 1, -3, -2, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ENERGYUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 1, -2, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    FORCEUNIT : IF
+      Dim = (IfcDimensionalExponents (1, 1, -2, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    FREQUENCYUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, -1, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    INDUCTANCEUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 1, -2, -2, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    ILLUMINANCEUNIT : IF
+      Dim = (IfcDimensionalExponents (-2, 0, 0, 0, 0, 0, 1))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    LUMINOUSFLUXUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 0, 0, 0, 0, 0, 1))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    MAGNETICFLUXUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 1, -2, -1, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    MAGNETICFLUXDENSITYUNIT : IF
+      Dim = (IfcDimensionalExponents (0, 1, -2, -1, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    POWERUNIT : IF
+      Dim = (IfcDimensionalExponents (2, 1, -3, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+    PRESSUREUNIT : IF
+      Dim = (IfcDimensionalExponents (-1, 1, -2, 0, 0, 0, 0))
+        THEN RETURN(TRUE);
+        ELSE RETURN(FALSE);
+      END_IF;
+  
+    OTHERWISE :
+      RETURN (UNKNOWN);
+  END_CASE;
+END_FUNCTION;
+
+FUNCTION IfcCorrectLocalPlacement
+	(AxisPlacement:IfcAxis2Placement; 
+     RelPlacement : IfcObjectPlacement)
+	: LOGICAL;
+  
+    IF (EXISTS(RelPlacement)) THEN
+      IF ('IFC2X3.IFCGRIDPLACEMENT' IN TYPEOF(RelPlacement)) THEN
+        RETURN(?);
+      END_IF;
+      IF ('IFC2X3.IFCLOCALPLACEMENT' IN TYPEOF(RelPlacement)) THEN
+        IF ('IFC2X3.IFCAXIS2PLACEMENT2D' IN TYPEOF(AxisPlacement)) THEN
+          RETURN(TRUE);
+        END_IF;
+        IF ('IFC2X3.IFCAXIS2PLACEMENT3D' IN TYPEOF(AxisPlacement)) THEN
+          IF (RelPlacement.RelativePlacement.Dim = 3) THEN
+            RETURN(TRUE);
+          ELSE
+            RETURN(FALSE);
+          END_IF;
+        END_IF;
+      END_IF;
+    ELSE
+      RETURN(TRUE);  
+    END_IF;
+    RETURN(?);
+END_FUNCTION;
+
+FUNCTION IfcCorrectObjectAssignment
+	(Constraint: IfcObjectTypeEnum; Objects : SET[1:?] OF IfcObjectDefinition)
+	: LOGICAL;
+    
+  LOCAL
+    Count : INTEGER := 0;
+  END_LOCAL;
+  
+      IF NOT(EXISTS(Constraint)) THEN 
+        RETURN(TRUE);
+      END_IF;
+    
+      CASE Constraint OF
+        IfcObjectTypeEnum.NOTDEFINED : RETURN(TRUE);
+        IfcObjectTypeEnum.PRODUCT :
+          BEGIN
+            Count := SIZEOF(QUERY(temp <* Objects | NOT('IFC2X3.IFCPRODUCT' IN TYPEOF(temp))));
+            RETURN(Count = 0);
+          END;
+        IfcObjectTypeEnum.PROCESS :
+          BEGIN
+            Count := SIZEOF(QUERY(temp <* Objects | NOT('IFC2X3.IFCPROCESS' IN TYPEOF(temp))));
+            RETURN(Count = 0);
+          END;
+        IfcObjectTypeEnum.CONTROL :
+          BEGIN
+            Count := SIZEOF(QUERY(temp <* Objects | NOT('IFC2X3.IFCCONTROL' IN TYPEOF(temp))));
+            RETURN(Count = 0);
+          END;
+        IfcObjectTypeEnum.RESOURCE :
+          BEGIN
+            Count := SIZEOF(QUERY(temp <* Objects | NOT('IFC2X3.IFCRESOURCE' IN TYPEOF(temp))));
+            RETURN(Count = 0);
+          END;
+        IfcObjectTypeEnum.ACTOR :
+          BEGIN
+            Count := SIZEOF(QUERY(temp <* Objects | NOT('IFC2X3.IFCACTOR' IN TYPEOF(temp))));
+            RETURN(Count = 0);
+          END;
+        IfcObjectTypeEnum.GROUP :
+          BEGIN
+            Count := SIZEOF(QUERY(temp <* Objects | NOT('IFC2X3.IFCGROUP' IN TYPEOF(temp))));
+            RETURN(Count = 0);
+          END;
+        IfcObjectTypeEnum.PROJECT :
+          BEGIN
+            Count := SIZEOF(QUERY(temp <* Objects | NOT('IFC2X3.IFCPROJECT' IN TYPEOF(temp))));
+            RETURN(Count = 0);
+          END;
+        OTHERWISE : RETURN(?);
+      END_CASE;
+END_FUNCTION;
+
+FUNCTION IfcCorrectUnitAssignment
+	(Units : SET [1:?] OF IfcUnit)
+	: LOGICAL;
+  
+    LOCAL
+      NamedUnitNumber    : INTEGER := 0;
+      DerivedUnitNumber  : INTEGER := 0;
+      MonetaryUnitNumber : INTEGER := 0;
+      NamedUnitNames     : SET OF IfcUnitEnum := [];
+      DerivedUnitNames   : SET OF IfcDerivedUnitEnum := [];
+    END_LOCAL;
+  
+    NamedUnitNumber    := SIZEOF(QUERY(temp <* Units | ('IFC2X3.IFCNAMEDUNIT' IN TYPEOF(temp)) AND NOT(temp.UnitType = IfcUnitEnum.USERDEFINED)));
+    DerivedUnitNumber  := SIZEOF(QUERY(temp <* Units | ('IFC2X3.IFCDERIVEDUNIT' IN TYPEOF(temp)) AND NOT(temp.UnitType = IfcDerivedUnitEnum.USERDEFINED)));
+    MonetaryUnitNumber := SIZEOF(QUERY(temp <* Units |  'IFC2X3.IFCMONETARYUNIT' IN TYPEOF(temp)));
+  
+    REPEAT i := 1 TO SIZEOF(Units);
+      IF (('IFC2X3.IFCNAMEDUNIT' IN TYPEOF(Units[i])) AND NOT(Units[i].UnitType = IfcUnitEnum.USERDEFINED)) THEN
+          NamedUnitNames := NamedUnitNames + Units[i].UnitType;
+      END_IF;
+      IF (('IFC2X3.IFCDERIVEDUNIT' IN TYPEOF(Units[i])) AND NOT(Units[i].UnitType = IfcDerivedUnitEnum.USERDEFINED)) THEN
+          DerivedUnitNames := DerivedUnitNames + Units[i].UnitType;
+      END_IF;
+    END_REPEAT;
+  
+    RETURN((SIZEOF(NamedUnitNames) = NamedUnitNumber) AND (SIZEOF(DerivedUnitNames) = DerivedUnitNumber) AND (MonetaryUnitNumber <= 1));
+END_FUNCTION;
+
+FUNCTION IfcCrossProduct
+	(Arg1, Arg2 : IfcDirection)
+	: IfcVector;
+  LOCAL
+    Mag : REAL;
+    Res : IfcDirection;
+    V1,V2  : LIST[3:3] OF REAL;
+    Result : IfcVector;
+  END_LOCAL;
+  
+    IF (NOT EXISTS (Arg1) OR (Arg1.Dim = 2)) OR (NOT EXISTS (Arg2) OR (Arg2.Dim = 2)) THEN
+      RETURN(?);
+    ELSE
+      BEGIN
+        V1  := IfcNormalise(Arg1).DirectionRatios;
+        V2  := IfcNormalise(Arg2).DirectionRatios;
+        Res := IfcRepresentationItem() || IfcGeometricRepresentationItem () 
+               || IfcDirection([(V1[2]*V2[3] - V1[3]*V2[2]), (V1[3]*V2[1] - V1[1]*V2[3]), (V1[1]*V2[2] - V1[2]*V2[1])]);
+        Mag := 0.0;
+        REPEAT i := 1 TO 3;
+          Mag := Mag + Res.DirectionRatios[i]*Res.DirectionRatios[i];
+        END_REPEAT;
+        IF (Mag > 0.0) THEN
+          Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector(Res, SQRT(Mag));
+        ELSE
+          Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector(Arg1, 0.0);
+        END_IF;
+        RETURN(Result);
+      END;
+    END_IF;
+END_FUNCTION;
+
+FUNCTION IfcCurveDim
+	(Curve : IfcCurve)
+	: IfcDimensionCount;
+  
+    IF ('IFC2X3.IFCLINE' IN TYPEOF(Curve))
+      THEN RETURN(Curve.Pnt.Dim);
+    END_IF;
+    IF ('IFC2X3.IFCCONIC' IN TYPEOF(Curve))
+      THEN RETURN(Curve.Position.Dim);
+    END_IF;
+    IF ('IFC2X3.IFCPOLYLINE' IN TYPEOF(Curve))
+      THEN RETURN(Curve.Points[1].Dim);
+    END_IF;
+    IF ('IFC2X3.IFCTRIMMEDCURVE' IN TYPEOF(Curve))
+      THEN RETURN(IfcCurveDim(Curve.BasisCurve));
+    END_IF;
+    IF ('IFC2X3.IFCCOMPOSITECURVE' IN TYPEOF(Curve))
+      THEN RETURN(Curve.Segments[1].Dim);
+    END_IF;
+    IF ('IFC2X3.IFCBSPLINECURVE' IN TYPEOF(Curve))
+      THEN RETURN(Curve.ControlPointsList[1].Dim);
+    END_IF;
+    IF ('IFC2X3.IFCOFFSETCURVE2D' IN TYPEOF(Curve))
+      THEN RETURN(2); 
+    END_IF;
+    IF ('IFC2X3.IFCOFFSETCURVE3D' IN TYPEOF(Curve))
+      THEN RETURN(3);
+    END_IF;
+  RETURN (?);
+END_FUNCTION;
+
+FUNCTION IfcCurveWeightsPositive
+	(B: IfcRationalBezierCurve)
+	: BOOLEAN;
+     LOCAL
+       Result : BOOLEAN := TRUE;
+     END_LOCAL;
+  
+     REPEAT i := 0 TO B.UpperIndexOnControlPoints;
+       IF B.Weights[i] <= 0.0  THEN
+         Result := FALSE;
+         RETURN(Result);
+       END_IF;
+     END_REPEAT;
+     RETURN(Result);
+END_FUNCTION;
+
+FUNCTION IfcDeriveDimensionalExponents
+	(x : IfcUnit)
+	: IfcDimensionalExponents;  
+    LOCAL
+      Result : IfcDimensionalExponents :=
+               IfcDimensionalExponents(0, 0, 0, 0, 0, 0, 0);  
+    END_LOCAL;
+    IF 'IFC2X3.IFCDERIVEDUNIT' IN TYPEOF(x) THEN
+      REPEAT i := LOINDEX(x.Elements) TO HIINDEX(x.Elements);
+        Result.LengthExponent :=        Result.LengthExponent +
+          (x.Elements[i].Exponent *
+           x.Elements[i].Unit.Dimensions.LengthExponent);
+        Result.MassExponent :=        Result.MassExponent  +
+          (x.Elements[i].Exponent *
+           x.Elements[i].Unit.Dimensions.MassExponent);
+        Result.TimeExponent :=        Result.TimeExponent +
+          (x.Elements[i].Exponent *
+           x.Elements[i].Unit.Dimensions.TimeExponent);
+        Result.ElectricCurrentExponent :=        Result.ElectricCurrentExponent +
+          (x.Elements[i].Exponent *
+           x.Elements[i].Unit.Dimensions.ElectricCurrentExponent);
+        Result.ThermodynamicTemperatureExponent :=
+          Result.ThermodynamicTemperatureExponent +
+          (x.Elements[i].Exponent *
+           x.Elements[i].Unit.Dimensions.ThermodynamicTemperatureExponent);
+        Result.AmountOfSubstanceExponent :=
+          Result.AmountOfSubstanceExponent +        (x.Elements[i].Exponent *
+           x.Elements[i].Unit.Dimensions.AmountOfSubstanceExponent);
+        Result.LuminousIntensityExponent :=
+          Result.LuminousIntensityExponent +        (x.Elements[i].Exponent *
+           x.Elements[i].Unit.Dimensions.LuminousIntensityExponent);
+      END_REPEAT;  
+    ELSE 
+      Result := x.Dimensions;  
+    END_IF;  
+  RETURN (Result);
+END_FUNCTION;
+
+FUNCTION IfcDimensionsForSiUnit
+	(n : IfcSiUnitName )
+	: IfcDimensionalExponents;
+    CASE n OF
+      METRE          : RETURN (IfcDimensionalExponents
+                               (1, 0, 0, 0, 0, 0, 0));
+      SQUARE_METRE   : RETURN (IfcDimensionalExponents
+                               (2, 0, 0, 0, 0, 0, 0));
+      CUBIC_METRE    : RETURN (IfcDimensionalExponents
+                               (3, 0, 0, 0, 0, 0, 0));
+      GRAM           : RETURN (IfcDimensionalExponents
+                               (0, 1, 0, 0, 0, 0, 0));
+      SECOND         : RETURN (IfcDimensionalExponents
+                               (0, 0, 1, 0, 0, 0, 0));
+      AMPERE         : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 1, 0, 0, 0));
+      KELVIN         : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 1, 0, 0));
+      MOLE           : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 0, 1, 0));
+      CANDELA        : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 0, 0, 1));
+      RADIAN         : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 0, 0, 0));
+      STERADIAN      : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 0, 0, 0));
+      HERTZ          : RETURN (IfcDimensionalExponents
+                               (0, 0, -1, 0, 0, 0, 0));
+      NEWTON         : RETURN (IfcDimensionalExponents
+                               (1, 1, -2, 0, 0, 0, 0));
+      PASCAL         : RETURN (IfcDimensionalExponents
+                               (-1, 1, -2, 0, 0, 0, 0));
+      JOULE          : RETURN (IfcDimensionalExponents
+                               (2, 1, -2, 0, 0, 0, 0));
+      WATT           : RETURN (IfcDimensionalExponents
+                               (2, 1, -3, 0, 0, 0, 0));
+      COULOMB        : RETURN (IfcDimensionalExponents
+                               (0, 0, 1, 1, 0, 0, 0));
+      VOLT           : RETURN (IfcDimensionalExponents
+                               (2, 1, -3, -1, 0, 0, 0));
+      FARAD          : RETURN (IfcDimensionalExponents
+                               (-2, -1, 4, 1, 0, 0, 0));
+      OHM            : RETURN (IfcDimensionalExponents
+                               (2, 1, -3, -2, 0, 0, 0));
+      SIEMENS        : RETURN (IfcDimensionalExponents
+                               (-2, -1, 3, 2, 0, 0, 0));
+      WEBER          : RETURN (IfcDimensionalExponents
+                               (2, 1, -2, -1, 0, 0, 0));
+      TESLA          : RETURN (IfcDimensionalExponents
+                               (0, 1, -2, -1, 0, 0, 0));
+      HENRY          : RETURN (IfcDimensionalExponents
+                               (2, 1, -2, -2, 0, 0, 0));
+      DEGREE_CELSIUS : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 1, 0, 0));
+      LUMEN          : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 0, 0, 1));
+      LUX            : RETURN (IfcDimensionalExponents
+                               (-2, 0, 0, 0, 0, 0, 1));
+      BECQUEREL      : RETURN (IfcDimensionalExponents
+                               (0, 0, -1, 0, 0, 0, 0));
+      GRAY           : RETURN (IfcDimensionalExponents
+                               (2, 0, -2, 0, 0, 0, 0));
+      SIEVERT        : RETURN (IfcDimensionalExponents
+                               (2, 0, -2, 0, 0, 0, 0));
+      OTHERWISE      : RETURN (IfcDimensionalExponents
+                               (0, 0, 0, 0, 0, 0, 0));
+    END_CASE;
+END_FUNCTION;
+
+FUNCTION IfcDotProduct
+	(Arg1, Arg2 : IfcDirection)
+	: REAL;
+  LOCAL
+    Scalar : REAL;
+    Vec1, Vec2 : IfcDirection;
+    Ndim   : INTEGER;
+  END_LOCAL;
+  
+    IF NOT EXISTS (Arg1) OR NOT EXISTS (Arg2) THEN
+      Scalar := ?;
+    ELSE
+      IF (Arg1.Dim <> Arg2.Dim) THEN
+        Scalar := ?;
+      ELSE
+        BEGIN
+          Vec1 := IfcNormalise(Arg1);
+          Vec2 := IfcNormalise(Arg2);
+          Ndim := Arg1.Dim;
+          Scalar := 0.0;
+          REPEAT i := 1 TO Ndim;
+            Scalar := Scalar + Vec1.DirectionRatios[i]*Vec2.DirectionRatios[i];
+          END_REPEAT;
+        END;
+      END_IF;
+    END_IF;
+    RETURN (Scalar);
+END_FUNCTION;
+
+FUNCTION IfcFirstProjAxis
+	(ZAxis, Arg : IfcDirection)
+	: IfcDirection;
+  LOCAL
+    XAxis : IfcDirection;
+    V     : IfcDirection;
+    Z     : IfcDirection;
+    XVec  : IfcVector;
+  END_LOCAL;
+  
+    IF (NOT EXISTS(ZAxis)) THEN
+      RETURN (?) ;
+    ELSE
+      Z := IfcNormalise(ZAxis);
+      IF NOT EXISTS(Arg) THEN
+        IF (Z.DirectionRatios <> [1.0,0.0,0.0]) THEN
+          V := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([1.0,0.0,0.0]);
+        ELSE
+          V := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0,1.0,0.0]);
+        END_IF;
+      ELSE
+        IF (Arg.Dim <> 3) THEN
+          RETURN (?) ;
+        END_IF;
+        IF ((IfcCrossProduct(Arg,Z).Magnitude) = 0.0) THEN
+          RETURN (?);
+        ELSE
+          V := IfcNormalise(Arg);
+        END_IF;
+      END_IF;
+      XVec  := IfcScalarTimesVector(IfcDotProduct(V, Z), Z);
+      XAxis := IfcVectorDifference(V, XVec).Orientation;
+      XAxis := IfcNormalise(XAxis);
+    END_IF;
+    RETURN(XAxis);
+END_FUNCTION;
+
+FUNCTION IfcLeapYear
+	(Year : IfcYearNumber)
+	: BOOLEAN;
+  
+  IF ((((Year MOD 4) = 0) AND ((Year MOD 100) <> 0)) OR
+              ((Year MOD 400) = 0)) THEN
+    RETURN(TRUE);
+  ELSE
+    RETURN(FALSE);
+  END_IF;
+END_FUNCTION;
+
+FUNCTION IfcListToArray
+	(Lis : LIST [0:?] OF GENERIC : T;
+         Low,U : INTEGER)
+	: ARRAY OF GENERIC : T;
+     LOCAL
+       N   : INTEGER;
+       Res : ARRAY [Low:U] OF GENERIC : T;
+     END_LOCAL;
+        
+     N := SIZEOF(Lis);
+     IF (N <> (U-Low +1)) THEN
+       RETURN(?);
+     ELSE
+       Res := [Lis[1] : N];
+       REPEAT i := 2 TO N;
+         Res[Low+i-1] := Lis[i];
+       END_REPEAT;
+       RETURN(Res);
+     END_IF;
+END_FUNCTION;
+
+FUNCTION IfcLoopHeadToTail
+	(ALoop : IfcEdgeLoop)
+	: LOGICAL;
+     LOCAL
+       N : INTEGER;
+       P : LOGICAL := TRUE;
+     END_LOCAL;
+       
+       N := SIZEOF (ALoop.EdgeList);
+       REPEAT i := 2 TO N;
+         P := P AND (ALoop.EdgeList[i-1].EdgeEnd :=:
+                     ALoop.EdgeList[i].EdgeStart);
+       END_REPEAT;     
+       RETURN (P);
+END_FUNCTION;
+
+FUNCTION IfcMlsTotalThickness
+	(LayerSet : IfcMaterialLayerSet)
+	: IfcLengthMeasure;
+    LOCAL
+      Max : IfcLengthMeasure := LayerSet.MaterialLayers[1].LayerThickness;    
+    END_LOCAL;
+  
+    IF SIZEOF(LayerSet.MaterialLayers) > 1 THEN
+      REPEAT i := 2 TO HIINDEX(LayerSet.MaterialLayers);
+         Max := Max + LayerSet.MaterialLayers[i].LayerThickness;
+      END_REPEAT;
+    END_IF;
+    RETURN (Max);
+END_FUNCTION;
+
+FUNCTION IfcNoOfLayers
+	(Element : IfcElement )
+	: INTEGER;
+      
+      LOCAL
+        Association : BAG OF IfcRelAssociates := [];
+        MaterialAssociation : SET OF IfcRelAssociatesMaterial := [];
+      END_LOCAL;
+      
+      Association := USEDIN(Element, 'IFC2X3.IFCRELASSOCIATES.RELATEDOBJECTS');
+   
+      IF SIZEOF (Association) > 0 THEN
+        REPEAT i := 1 TO HIINDEX(Association);
+          IF ('IFC2X3.IFCRELASSOCIATESMATERIAL' IN TYPEOF(Association[i])) THEN 
+            MaterialAssociation := MaterialAssociation + Association[i];
+          END_IF;
+        END_REPEAT;
+      END_IF;
+      
+      IF (SIZEOF(MaterialAssociation) <> 1) THEN
+        RETURN (?);
+      ELSE
+        IF 'IFC2X3.IFCMATERIAL' IN TYPEOF(MaterialAssociation[1].RelatingMaterial) THEN
+           RETURN (1);
+        END_IF;
+        IF 'IFC2X3.IFCMATERIALLAYERSETUSAGE' IN TYPEOF(MaterialAssociation[1].RelatingMaterial) THEN
+           RETURN (SIZEOF(MaterialAssociation[1].RelatingMaterial.ForLayerSet.MaterialLayers));
+        END_IF;
+        IF 'IFC2X3.IFCMATERIALLIST' IN TYPEOF(MaterialAssociation[1].RelatingMaterial) THEN
+           RETURN (?);
+        END_IF;
+      END_IF;
+    
+      RETURN (?);
+END_FUNCTION;
+
+FUNCTION IfcNormalise
+	(Arg : IfcVectorOrDirection)
+	: IfcVectorOrDirection;
+  LOCAL
+    Ndim : INTEGER;
+    V    : IfcDirection
+         := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([1.,0.]); 
+    Vec  : IfcVector 
+         := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector (
+              IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([1.,0.]), 1.);
+    Mag  : REAL;
+    Result : IfcVectorOrDirection
+           := V;
+  END_LOCAL;
+  
+    IF NOT EXISTS (Arg) THEN
+      RETURN (?);
+    ELSE
+      Ndim := Arg.Dim;
+      IF 'IFC2X3.IFCVECTOR' IN TYPEOF(Arg) THEN
+        BEGIN
+  	V.DirectionRatios := Arg.Orientation.DirectionRatios;
+          Vec.Magnitude := Arg.Magnitude;
+  	Vec.Orientation := V;
+          IF Arg.Magnitude = 0.0 THEN
+            RETURN(?);
+          ELSE
+            Vec.Magnitude := 1.0;
+          END_IF;
+        END;
+      ELSE
+        V.DirectionRatios := Arg.DirectionRatios;
+      END_IF;
+      Mag := 0.0;
+        REPEAT i := 1 TO Ndim;
+          Mag := Mag + V.DirectionRatios[i]*V.DirectionRatios[i];
+        END_REPEAT;
+      IF Mag > 0.0 THEN
+        Mag := SQRT(Mag);
+        REPEAT i := 1 TO Ndim;
+          V.DirectionRatios[i] := V.DirectionRatios[i]/Mag;
+        END_REPEAT;
+        IF 'IFC2X3.IFCVECTOR' IN TYPEOF(arg) THEN
+          Vec.Orientation := V;
+          Result := Vec;
+        ELSE
+          Result := V;
+        END_IF;
+      ELSE
+        RETURN(?);
+      END_IF;
+    END_IF;
+    RETURN (Result);
+END_FUNCTION;
+
+FUNCTION IfcOrthogonalComplement
+	(Vec : IfcDirection)
+	: IfcDirection;
+  LOCAL
+    Result : IfcDirection ;
+  END_LOCAL;
+    IF NOT EXISTS (Vec) OR (Vec.Dim <> 2) THEN
+      RETURN(?);
+    ELSE
+      Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([-Vec.DirectionRatios[2], Vec.DirectionRatios[1]]);
+      RETURN(Result);
+    END_IF;
+END_FUNCTION;
+
+FUNCTION IfcPathHeadToTail
+	(APath : IfcPath)
+	: LOGICAL;
+     LOCAL
+       N : INTEGER := 0;
+       P : LOGICAL := UNKNOWN;
+     END_LOCAL;
+       N := SIZEOF (APath.EdgeList);
+     REPEAT i := 2 TO N;
+        P := P AND (APath.EdgeList[i-1].EdgeEnd :=:
+                    APath.EdgeList[i].EdgeStart);
+     END_REPEAT;
+     RETURN (P);
+END_FUNCTION;
+
+FUNCTION IfcSameAxis2Placement
+	(ap1, ap2 : IfcAxis2Placement; Epsilon : REAL)
+	: LOGICAL;
+  
+    RETURN (IfcSameDirection(ap1.P[1],ap2.P[1],Epsilon) AND
+            IfcSameDirection(ap1.P[2],ap2.P[2],Epsilon) AND
+            IfcSameCartesianPoint(ap1.Location,ap1.Location,Epsilon));
+END_FUNCTION;
+
+FUNCTION IfcSameCartesianPoint
+	(cp1, cp2 : IfcCartesianPoint; Epsilon : REAL)
+	: LOGICAL;
+    
+    LOCAL
+      cp1x : REAL := cp1.Coordinates[1];
+      cp1y : REAL := cp1.Coordinates[2];
+      cp1z : REAL := 0;
+      cp2x : REAL := cp2.Coordinates[1];
+      cp2y : REAL := cp2.Coordinates[2];
+      cp2z : REAL := 0;
+    END_LOCAL;
+  
+    IF (SIZEOF(cp1.Coordinates) > 2) THEN
+      cp1z := cp1.Coordinates[3];
+    END_IF;
+  
+    IF (SIZEOF(cp2.Coordinates) > 2) THEN
+      cp2z := cp2.Coordinates[3];
+    END_IF;
+  
+    RETURN (IfcSameValue(cp1x,cp2x,Epsilon) AND
+            IfcSameValue(cp1y,cp2y,Epsilon) AND
+            IfcSameValue(cp1z,cp2z,Epsilon));
+END_FUNCTION;
+
+FUNCTION IfcSameDirection
+	(dir1, dir2 : IfcDirection; Epsilon : REAL)
+	: LOGICAL;
+    LOCAL
+      dir1x : REAL := dir1.DirectionRatios[1];
+      dir1y : REAL := dir1.DirectionRatios[2];
+      dir1z : REAL := 0;
+      dir2x : REAL := dir2.DirectionRatios[1];
+      dir2y : REAL := dir2.DirectionRatios[2];
+      dir2z : REAL := 0;
+    END_LOCAL;
+  
+    IF (SIZEOF(dir1.DirectionRatios) > 2) THEN
+      dir1z := dir1.DirectionRatios[3];
+    END_IF;
+  
+    IF (SIZEOF(dir2.DirectionRatios) > 2) THEN
+      dir2z := dir2.DirectionRatios[3];
+    END_IF;
+    
+    RETURN (IfcSameValue(dir1x,dir2x,Epsilon) AND
+            IfcSameValue(dir1y,dir2y,Epsilon) AND
+            IfcSameValue(dir1z,dir2z,Epsilon));
+END_FUNCTION;
+
+FUNCTION IfcSameValidPrecision
+	(Epsilon1, Epsilon2 : REAL)
+	: LOGICAL;
+    LOCAL
+      ValidEps1, ValidEps2 : REAL;
+      DefaultEps           : REAL := 0.000001;
+      DerivationOfEps      : REAL := 1.001;
+      UpperEps             : REAL := 1.0;
+    END_LOCAL;
+    
+      ValidEps1 := NVL(Epsilon1, DefaultEps);
+      ValidEps2 := NVL(Epsilon2, DefaultEps);
+      RETURN ((0.0 < ValidEps1) AND (ValidEps1 <= (DerivationOfEps * ValidEps2)) AND 
+              (ValidEps2 <= (DerivationOfEps * ValidEps1)) AND (ValidEps2 < UpperEps));
+END_FUNCTION;
+
+FUNCTION IfcSameValue
+	(Value1, Value2 : REAL; Epsilon : REAL)
+	: LOGICAL;
+    LOCAL
+      ValidEps    : REAL;
+      DefaultEps  : REAL := 0.000001;
+    END_LOCAL;
+    
+    ValidEps := NVL(Epsilon, DefaultEps);
+    RETURN ((Value1 + ValidEps > Value2) AND (Value1 < Value2 + ValidEps));
+END_FUNCTION;
+
+FUNCTION IfcScalarTimesVector
+	(Scalar : REAL; Vec : IfcVectorOrDirection)
+	: IfcVector;
+  LOCAL
+    V : IfcDirection;
+    Mag : REAL;
+    Result : IfcVector;
+  END_LOCAL;
+  
+    IF NOT EXISTS (Scalar) OR NOT EXISTS (Vec) THEN
+      RETURN (?) ;
+    ELSE
+      IF 'IFC2X3.IFCVECTOR' IN TYPEOF (Vec) THEN
+        V := Vec.Orientation;
+        Mag := Scalar * Vec.Magnitude;
+      ELSE
+        V := Vec;
+        Mag := Scalar;
+      END_IF;
+      IF (Mag < 0.0 ) THEN
+        REPEAT i := 1 TO SIZEOF(V.DirectionRatios);
+          V.DirectionRatios[i] := -V.DirectionRatios[i];
+        END_REPEAT;
+        Mag := -Mag;
+      END_IF;
+      Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector(IfcNormalise(V), Mag);
+    END_IF;
+    RETURN (Result);
+END_FUNCTION;
+
+FUNCTION IfcSecondProjAxis
+	(ZAxis, XAxis, Arg: IfcDirection)
+	: IfcDirection;
+  LOCAL
+    YAxis : IfcVector;
+    V     : IfcDirection;
+    Temp  : IfcVector;
+  END_LOCAL;
+  
+    IF NOT EXISTS(Arg) THEN
+      V := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0,1.0,0.0]);
+    ELSE
+      V := Arg;
+    END_IF;
+    Temp  := IfcScalarTimesVector(IfcDotProduct(V, ZAxis), ZAxis);
+    YAxis := IfcVectorDifference(V, Temp);
+    Temp  := IfcScalarTimesVector(IfcDotProduct(V, XAxis), XAxis);
+    YAxis := IfcVectorDifference(YAxis, Temp);
+    YAxis := IfcNormalise(YAxis);
+    RETURN(YAxis.Orientation);
+END_FUNCTION;
+
+FUNCTION IfcShapeRepresentationTypes
+	(RepType : IfcLabel; Items : SET OF IfcRepresentationItem)
+	: LOGICAL;
+      
+      LOCAL
+        Count : INTEGER := 0;
+      END_LOCAL;
+  
+      CASE RepType OF 
+      'Curve2D' :
+        BEGIN 
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCCURVE' IN TYPEOF(temp)) 
+                   AND (temp.Dim = 2)));
+        END;
+      'Annotation2D' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | (
+                    SIZEOF(TYPEOF(temp) * [
+                     'IFC2X3.IFCPOINT',
+                     'IFC2X3.IFCCURVE',
+                     'IFC2X3.IFCGEOMETRICCURVESET',
+                     'IFC2X3.IFCANNOTATIONFILLAREA',
+                     'IFC2X3.IFCDEFINEDSYMBOL',
+                     'IFC2X3.IFCTEXTLITERAL',
+                     'IFC2X3.IFCDRAUGHTINGCALLOUT']) = 1)
+                   ));
+        END;
+      'GeometricSet' : 
+        BEGIN 
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCGEOMETRICSET' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCPOINT' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCCURVE' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCSURFACE' IN TYPEOF(temp))));
+        END;
+      'GeometricCurveSet' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCGEOMETRICCURVESET' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCGEOMETRICSET' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCPOINT' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCCURVE' IN TYPEOF(temp))));
+           REPEAT i:=1 TO HIINDEX(Items);  
+             IF ('IFC2X3.IFCGEOMETRICSET' IN TYPEOF(Items[i]))
+             THEN
+               IF (SIZEOF(QUERY(temp <* Items[i]\IfcGeometricSet.Elements | 'IFC2X3.IFCSURFACE' IN TYPEOF(temp))) > 0)
+               THEN
+                 Count := Count - 1;
+               END_IF;
+             END_IF;
+           END_REPEAT;
+        END;
+      'SurfaceModel' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | SIZEOF([
+                     'IFC2X3.IFCSHELLBASEDSURFACEMODEL',
+                     'IFC2X3.IFCFACEBASEDSURFACEMODEL',
+                     'IFC2X3.IFCFACETEDBREP',
+                     'IFC2X3.IFCFACETEDBREPWITHVOIDS'] * TYPEOF(temp)) >= 1
+                   ));      
+        END;
+      'SolidModel' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCSOLIDMODEL' IN TYPEOF(temp))));            
+        END;
+      'SweptSolid' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCSWEPTAREASOLID' IN TYPEOF(temp))));            
+        END;
+      'CSG' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCBOOLEANRESULT' IN TYPEOF(temp))));            
+        END;
+      'Clipping' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCBOOLEANCLIPPINGRESULT' IN TYPEOF(temp))));            
+        END;
+      'AdvancedSweptSolid' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCSURFACECURVESWEPTAREASOLID' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCSWEPTDISKSOLID' IN TYPEOF(temp))));      
+        END;
+      'Brep' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCFACETEDBREP' IN TYPEOF(temp))
+                   OR ('IFC2X3.IFCFACETEDBREPWITHVOIDS' IN TYPEOF(temp))));      
+        END;
+      'BoundingBox' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCBOUNDINGBOX' IN TYPEOF(temp))));
+          IF (SIZEOF(Items) > 1)
+          THEN
+            Count := 0;
+          END_IF;   
+        END;
+      'SectionedSpine' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCSECTIONEDSPINE' IN TYPEOF(temp))));      
+        END;
+      'MappedRepresentation' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | ('IFC2X3.IFCMAPPEDITEM' IN TYPEOF(temp))));  
+        END;
+       OTHERWISE : RETURN(?);
+      END_CASE;
+      RETURN (Count = SIZEOF(Items));
+END_FUNCTION;
+
+FUNCTION IfcTopologyRepresentationTypes
+	(RepType : IfcLabel; Items : SET OF IfcRepresentationItem)
+	: LOGICAL;
+      
+      LOCAL
+        Count : INTEGER := 0;
+      END_LOCAL;
+  
+      CASE RepType OF 
+      'Vertex' :
+        BEGIN 
+          Count := SIZEOF(QUERY(temp <* Items | 
+                    ('IFC2X3.IFCVERTEX' IN TYPEOF(temp))));
+        END;
+      'Edge' : 
+        BEGIN 
+          Count := SIZEOF(QUERY(temp <* Items | 
+                    ('IFC2X3.IFCEDGE' IN TYPEOF(temp))));
+        END;
+      'Path' : 
+        BEGIN 
+          Count := SIZEOF(QUERY(temp <* Items | 
+                    ('IFC2X3.IFCPATH' IN TYPEOF(temp))));
+        END;
+      'Face' : 
+        BEGIN 
+          Count := SIZEOF(QUERY(temp <* Items | 
+                    ('IFC2X3.IFCFACE' IN TYPEOF(temp))));
+        END;
+      'Shell' :
+        BEGIN
+          Count := SIZEOF(QUERY(temp <* Items | 
+                    ('IFC2X3.IFCOPENSHELL' IN TYPEOF(temp))
+                      OR ('IFC2X3.IFCCLOSEDSHELL' IN TYPEOF(temp))));
+        END;
+      'Undefined': RETURN(TRUE);
+       OTHERWISE : RETURN(?);
+      END_CASE;
+      RETURN (Count = SIZEOF(Items));
+END_FUNCTION;
+
+FUNCTION IfcUniquePropertyName
+	(Properties : SET [1:?] OF IfcProperty)
+	: LOGICAL;
+  
+  LOCAL
+    Names : SET OF IfcIdentifier := [];
+  END_LOCAL;
+  
+  REPEAT i:=1 TO HIINDEX(Properties);
+    Names := Names + Properties[i].Name;
+  END_REPEAT;
+  RETURN (SIZEOF(Names) = SIZEOF(Properties));
+END_FUNCTION;
+
+FUNCTION IfcValidCalendarDate
+	(Date : IfcCalendarDate)
+	: LOGICAL;
+  IF NOT ({1 <= Date.DayComponent <= 31}) THEN    
+    RETURN(FALSE);  
+  END_IF;
+  CASE Date.MonthComponent OF
+    4         : RETURN({ 1<= Date.DayComponent <= 30});
+    6         : RETURN({ 1<= Date.DayComponent <= 30});
+    9         : RETURN({ 1<= Date.DayComponent <= 30});
+    11        : RETURN({ 1<= Date.DayComponent <= 30});    
+    2         :    
+    BEGIN
+      IF (IfcLeapYear(Date.YearComponent)) THEN
+        RETURN({ 1<= Date.DayComponent <= 29});      
+      ELSE
+        RETURN({ 1<= Date.DayComponent <= 28});      
+      END_IF;    
+    END;
+    OTHERWISE : RETURN(TRUE);  
+  END_CASE;
+END_FUNCTION;
+
+FUNCTION IfcValidTime
+	(Time: IfcLocalTime)
+	: BOOLEAN;
+  IF EXISTS (Time.SecondComponent) THEN
+    RETURN (EXISTS (Time.MinuteComponent));  
+  ELSE    
+    RETURN (TRUE);  
+  END_IF;
+END_FUNCTION;
+
+FUNCTION IfcVectorDifference
+	(Arg1, Arg2 : IfcVectorOrDirection)
+	: IfcVector;
+  LOCAL
+    Result : IfcVector;
+    Res, Vec1, Vec2 : IfcDirection;
+    Mag, Mag1, Mag2 : REAL;
+    Ndim : INTEGER;
+  END_LOCAL;
+  
+    IF ((NOT EXISTS (Arg1)) OR (NOT EXISTS (Arg2))) OR (Arg1.Dim <> Arg2.Dim) THEN
+      RETURN (?) ;
+    ELSE
+      BEGIN
+        IF 'IFC2X3.IFCVECTOR' IN TYPEOF(Arg1) THEN
+          Mag1 := Arg1.Magnitude;
+          Vec1 := Arg1.Orientation;
+        ELSE
+          Mag1 := 1.0;
+          Vec1 := Arg1;
+        END_IF;
+        IF 'IFC2X3.IFCVECTOR' IN TYPEOF(Arg2) THEN
+          Mag2 := Arg2.Magnitude;
+          Vec2 := Arg2.Orientation;
+        ELSE
+          Mag2 := 1.0;
+          Vec2 := Arg2;
+        END_IF;
+        Vec1 := IfcNormalise (Vec1);
+        Vec2 := IfcNormalise (Vec2);
+        Ndim := SIZEOF(Vec1.DirectionRatios);
+        Mag  := 0.0;
+        Res  := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0:Ndim]);
+  
+        REPEAT i := 1 TO Ndim;
+          Res.DirectionRatios[i] := Mag1*Vec1.DirectionRatios[i] - Mag2*Vec2.DirectionRatios[i];
+          Mag := Mag + (Res.DirectionRatios[i]*Res.DirectionRatios[i]);
+        END_REPEAT;
+  
+        IF (Mag > 0.0 ) THEN
+          Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector( Res, SQRT(Mag));
+        ELSE
+          Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector( Vec1, 0.0);
+        END_IF;
+      END;
+    END_IF;
+    RETURN (Result);
+END_FUNCTION;
+
+FUNCTION IfcVectorSum
+	(Arg1, Arg2 : IfcVectorOrDirection)
+	: IfcVector;
+  LOCAL
+    Result : IfcVector;
+    Res, Vec1, Vec2 : IfcDirection;
+    Mag, Mag1, Mag2 : REAL;
+    Ndim : INTEGER;
+  END_LOCAL;
+  
+    IF ((NOT EXISTS (Arg1)) OR (NOT EXISTS (Arg2))) OR (Arg1.Dim <> Arg2.Dim) THEN
+      RETURN (?) ;
+    ELSE
+      BEGIN
+        IF 'IFC2X3.IFCVECTOR' IN TYPEOF(Arg1) THEN
+          Mag1 := Arg1.Magnitude;
+          Vec1 := Arg1.Orientation;
+        ELSE
+          Mag1 := 1.0;
+          Vec1 := Arg1;
+        END_IF;
+        IF 'IFC2X3.IFCVECTOR' IN TYPEOF(Arg2) THEN
+          Mag2 := Arg2.Magnitude;
+          Vec2 := Arg2.Orientation;
+        ELSE
+          Mag2 := 1.0;
+          Vec2 := Arg2;
+        END_IF;
+        Vec1 := IfcNormalise (Vec1);
+        Vec2 := IfcNormalise (Vec2);
+        Ndim := SIZEOF(Vec1.DirectionRatios);
+        Mag  := 0.0;
+        Res  := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcDirection([0.0:Ndim]);
+  
+        REPEAT i := 1 TO Ndim;
+          Res.DirectionRatios[i] := Mag1*Vec1.DirectionRatios[i] + Mag2*Vec2.DirectionRatios[i];
+          Mag := Mag + (Res.DirectionRatios[i]*Res.DirectionRatios[i]);
+        END_REPEAT;
+  
+        IF (Mag > 0.0 ) THEN
+          Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector( Res, SQRT(Mag));
+        ELSE
+          Result := IfcRepresentationItem() || IfcGeometricRepresentationItem () || IfcVector( Vec1, 0.0);
+        END_IF;
+      END;
+    END_IF;
+    RETURN (Result);
+END_FUNCTION;
+
+RULE IfcRepresentationContextSameWCS FOR 
+	(IfcGeometricRepresentationContext);
+    LOCAL
+      IsDifferent  : LOGICAL := FALSE;
+    END_LOCAL;
+      IF (SIZEOF(IfcGeometricRepresentationContext) > 1)
+      THEN
+        REPEAT i := 2 TO HIINDEX(IfcGeometricRepresentationContext);
+          IF (IfcGeometricRepresentationContext[1].WorldCoordinateSystem :<>: IfcGeometricRepresentationContext[i].WorldCoordinateSystem)
+          THEN
+            IsDifferent := (NOT(IfcSameValidPrecision(IfcGeometricRepresentationContext[1].Precision,
+                                                      IfcGeometricRepresentationContext[i].Precision)))
+                        OR (NOT(IfcSameAxis2Placement(IfcGeometricRepresentationContext[1].WorldCoordinateSystem,
+                                                      IfcGeometricRepresentationContext[i].WorldCoordinateSystem,
+                                                      IfcGeometricRepresentationContext[1].Precision)));
+            IF (IsDifferent = TRUE) THEN
+              ESCAPE;
+            END_IF;
+          END_IF;
+        END_REPEAT;
+      END_IF;
+    WHERE
+      WR1 : IsDifferent = FALSE;
+END_RULE;
+
+RULE IfcSingleProjectInstance FOR 
+	(IfcProject);
+    WHERE
+      WR1 : SIZEOF(IfcProject) <= 1;
+END_RULE;
+
+END_SCHEMA;

+ 0 - 33
test/RunSingleUnitTestSuite.bat

@@ -1,33 +0,0 @@
-
-rem ------------------------------------------------------------------------------
-rem Tiny script to execute a single unit test suite.
-rem 
-rem Usage:
-rem    SET  OUTDIR=<directory_for_test_results>
-rem    SET  BINDIR=<directory_where_binaries_are_stored>
-rem
-rem    CALL RunSingleUnitTestSuite <name_of_test> <output_file>
-rem
-rem Post:
-rem    FIRSTUTNA       - if the test wasn't found, receives the test name
-rem    FIRSTUTFAILUR   - if the test failed, receives the test name
-rem
-rem ------------------------------------------------------------------------------
-IF NOT EXIST %BINDIR%\%1\unit.exe (
-
-   echo NOT AVAILABLE. Please rebuild this configuration
-   echo Unable to find %BINDIR%\%1\unit.exe > %OUTDIR%%2
-   SET FIRSTUTNA=%2
-) ELSE (
-
-   %BINDIR%\%1\unit.exe > %OUTDIR%%2
-   IF errorlevel == 0 ( 
-      echo SUCCESS
-   ) ELSE (
-      echo FAILURE, check output file: %2
-      SET FIRSTUTFAILURE=%2
-   )
-)
-
-echo.
-echo.

+ 0 - 94
test/RunUnitTestSuite.bat

@@ -1,94 +0,0 @@
-rem ------------------------------------------------------------------------------
-rem Tiny script to execute Assimp's fully unit test suite for all configurations
-rem 
-rem Usage: call RunUnitTestSuite
-rem ------------------------------------------------------------------------------
-
-rem Setup the console environment
-set errorlevel=0
-color 4e
-cls
-
-@echo off
-
-rem Setup target architecture
-SET ARCHEXT=x64
-IF %PROCESSOR_ARCHITECTURE% == x86 (
-   SET ARCHEXT=win32
-)
-
-rem Setup standard paths from here
-SET OUTDIR=results\
-SET BINDIR=..\bin\
-SET FIRSTUTFAILURE=nil
-SET FIRSTUTNA=nil
-
-echo #=====================================================================
-echo # Open Asset Import Library - Unittests                               
-echo #=====================================================================
-echo #                                                                     
-echo # Executes the Assimp library unit test suite for the following                
-echo # build configurations (if available):                                               
-echo #                                                                     
-echo #  Release                                                           
-echo #  Release -st                                                        
-echo #  Release -noboost                                                   
-echo #  Release -dll                                                       
-echo #                                                                     
-echo #  Debug                                                              
-echo #  Debug   -st                                                        
-echo #  Debug   -noboost                                                   
-echo #  Debug   -dll                                                                                                                        
-echo ======================================================================
-echo.
-echo.
-
-
-echo assimp-core release 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release_%ARCHEXT% release.txt
-
-echo assimp-core release -st 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release-st_%ARCHEXT% release-st.txt
-
-echo assimp-core release -noboost 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release-noboost-st_%ARCHEXT% release-st-noboost.txt
-
-echo assimp-core release -dll 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release-dll_%ARCHEXT% release-dll.txt
-
-echo assimp-core debug
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug_%ARCHEXT% debug.txt
-
-echo assimp-core debug -st 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug-st_%ARCHEXT% debug-st.txt
-
-echo assimp-core debug -noboost 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug-noboost-st_%ARCHEXT% debug-st-noboost.txt
-
-echo assimp-core debug -dll 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug-dll_%ARCHEXT% debug-dll.txt
-
-
-echo ======================================================================
-IF %FIRSTUTNA% == nil (
-   echo All test configs have been found.
-) ELSE (
-   echo One or more test configs are not available.
-)
-
-IF %FIRSTUTFAILURE% == nil (
-   echo All tests have been successful. 
-) ELSE (
-   echo One or more tests failed.
-)
-echo.
-
-pause

BIN
test/models-nonbsd/FBX/2013_BINARY/anims_with_full_rotations_between_keys.fbx


BIN
test/models-nonbsd/FBX/2013_BINARY/multiple_animations_test.fbx


+ 754 - 0
test/models-nonbsd/PLY/ant-half.ply

@@ -0,0 +1,754 @@
+ply
+format ascii 1.0
+element vertex 486
+property float32 x
+property float32 y
+property float32 z
+element face 912
+property list uint8 int32 vertex_indices
+end_header
+-1.106 3.844 9.073 
+-0.3523 0.4402 11.07 
+1.028 3.76 9.209 
+0.137 -0.5632 10.73 
+2.01 4.503 5.887 
+0.07813 5.232 6.794 
+-0.7266 3.741 3.839 
+-2.789 3.179 5.07 
+-0.9185 2.402 3.279 
+1.445 2.139 3.394 
+-3.114 1.498 5.285 
+-1.317 -1.269 8.385 
+-0.854 -1.319 5.036 
+-0.9351 5.347 0.6162 
+-0.8184 2.622 3.235 
+0.4875 5.529 -0.2241 
+3.193 2.756 1.633 
+3.213 1.145 -2.568 
+-2.25 1.208 2.767 
+0.3225 0.8339 3.323 
+1.354 -1.725 1.105 
+0.1887 1.133 -5.785 
+-3.637 2.696 0.3325 
+-3.706 0.8936 -0.5452 
+-0.4326 -0.8737 -4.095 
+-2.994 -0.4858 0.9023 
+0.1252 -2.079 -1.51 
+2.856 -0.7459 -1.187 
+2.32 3.733 8.13 
+2.031 3.721 9.095 
+2.819 3.567 8.537 
+1.994 2.581 9.711 
+2.64 2.491 9.542 
+3.187 2.528 8.375 
+1.628 2.491 7.518 
+1.62 3.721 8.274 
+0.9868 2.471 8.914 
+1.552 2.106 9.414 
+2.657 1.774 8.918 
+-1.805 3.733 8.13 
+-2.094 3.721 9.095 
+-1.306 3.567 8.537 
+-2.131 2.581 9.711 
+-1.485 2.491 9.542 
+-0.938 2.528 8.375 
+-2.497 2.491 7.518 
+-2.505 3.721 8.274 
+-3.138 2.471 8.914 
+-2.573 2.106 9.414 
+-1.469 1.774 8.918 
+1.549 3.638 6.803 
+1.355 3.638 6.7 
+1.424 5.126 6.883 
+1.615 5.083 6.981 
+1.169 3.638 6.815 
+1.237 5.115 6.997 
+1.176 3.638 7.035 
+1.241 5.061 7.21 
+1.369 3.638 7.138 
+1.433 5.018 7.308 
+1.556 3.638 7.023 
+1.62 5.029 7.194 
+1.625 6.512 7.421 
+1.811 6.429 7.504 
+1.437 6.49 7.531 
+1.434 6.386 7.724 
+1.619 6.304 7.807 
+1.808 6.326 7.697 
+1.945 7.702 8.276 
+2.121 7.585 8.335 
+1.754 7.672 8.38 
+1.74 7.525 8.542 
+1.916 7.408 8.601 
+2.107 7.439 8.497 
+2.362 8.615 9.391 
+2.526 8.473 9.417 
+2.168 8.578 9.487 
+2.138 8.398 9.608 
+2.303 8.255 9.635 
+2.497 8.293 9.539 
+2.847 9.189 10.69 
+2.998 9.03 10.68 
+2.649 9.148 10.78 
+2.603 8.947 10.85 
+2.753 8.788 10.84 
+2.95 8.83 10.75 
+3.368 9.385 12.08 
+3.503 9.22 12.03 
+3.167 9.342 12.16 
+3.101 9.134 12.18 
+3.236 8.97 12.13 
+3.438 9.013 12.06 
+3.889 9.189 13.48 
+4.01 9.03 13.39 
+3.684 9.148 13.54 
+3.599 8.947 13.51 
+3.719 8.788 13.42 
+3.925 8.83 13.36 
+4.374 8.615 14.77 
+4.481 8.473 14.65 
+4.165 8.578 14.83 
+4.063 8.398 14.76 
+4.17 8.255 14.63 
+4.379 8.293 14.57 
+4.791 7.702 15.89 
+4.886 7.585 15.73 
+4.579 7.672 15.94 
+4.462 7.525 15.82 
+4.556 7.408 15.66 
+4.769 7.439 15.62 
+5.111 6.512 16.74 
+5.196 6.429 16.56 
+4.896 6.49 16.78 
+4.768 6.386 16.64 
+4.853 6.304 16.46 
+5.068 6.326 16.42 
+-1.141 5.126 6.883 
+-1.072 3.638 6.7 
+-1.266 3.638 6.803 
+-1.332 5.083 6.981 
+-0.9541 5.115 6.997 
+-0.886 3.638 6.815 
+-0.9585 5.061 7.21 
+-0.8928 3.638 7.035 
+-1.15 5.018 7.308 
+-1.086 3.638 7.138 
+-1.337 5.029 7.194 
+-1.272 3.638 7.023 
+-1.342 6.512 7.421 
+-1.528 6.429 7.504 
+-1.154 6.49 7.531 
+-1.151 6.386 7.724 
+-1.336 6.304 7.807 
+-1.525 6.326 7.697 
+-1.662 7.702 8.276 
+-1.838 7.585 8.335 
+-1.471 7.672 8.38 
+-1.457 7.525 8.542 
+-1.633 7.408 8.601 
+-1.824 7.439 8.497 
+-2.079 8.615 9.391 
+-2.243 8.473 9.417 
+-1.885 8.578 9.487 
+-1.855 8.398 9.608 
+-2.02 8.255 9.635 
+-2.214 8.293 9.539 
+-2.564 9.189 10.69 
+-2.715 9.03 10.68 
+-2.366 9.148 10.78 
+-2.32 8.947 10.85 
+-2.47 8.788 10.84 
+-2.667 8.83 10.75 
+-3.085 9.385 12.08 
+-3.22 9.22 12.03 
+-2.884 9.342 12.16 
+-2.818 9.134 12.18 
+-2.953 8.97 12.13 
+-3.155 9.013 12.06 
+-3.606 9.189 13.48 
+-3.726 9.03 13.39 
+-3.4 9.148 13.54 
+-3.316 8.947 13.51 
+-3.437 8.788 13.42 
+-3.642 8.83 13.36 
+-4.091 8.615 14.77 
+-4.198 8.473 14.65 
+-3.882 8.578 14.83 
+-3.78 8.398 14.76 
+-3.887 8.255 14.63 
+-4.096 8.293 14.57 
+-4.508 7.702 15.89 
+-4.603 7.585 15.73 
+-4.296 7.672 15.94 
+-4.179 7.525 15.82 
+-4.273 7.408 15.66 
+-4.485 7.439 15.62 
+-4.828 6.512 16.74 
+-4.913 6.429 16.56 
+-4.613 6.49 16.78 
+-4.484 6.386 16.64 
+-4.57 6.304 16.46 
+-4.784 6.326 16.42 
+-1.519 -2.27 2.989 
+-1.987 -1.082 3.408 
+-2.709 -1.989 3.536 
+-1.513 -2.259 2.974 
+-2.524 -1.536 2.471 
+-4.318 -0.3933 4.187 
+-4.692 -0.6204 3.123 
+-6.274 0.9227 4.173 
+-5.533 1.852 4.043 
+-6.084 1.387 3.082 
+-6.844 2.279 4.015 
+-6.83 1.957 4.012 
+-6.886 2.118 3.737 
+-7.536 1.346 4.658 
+-7.229 0.9683 4.298 
+-8.053 1.724 3.821 
+-7.747 1.346 3.46 
+-9.085 -0.1982 5.078 
+-9.347 -0.1982 3.597 
+-8.702 -0.7393 4.247 
+-10.91 -1.528 5.154 
+-10.39 -2.11 4.847 
+-11.08 -1.528 4.148 
+-10.49 -2.11 4.26 
+-11.58 -2.509 4.768 
+-11.57 -2.523 4.76 
+-11.59 -2.509 4.742 
+-11.57 -2.523 4.744 
+-12.39 -3.546 5.269 
+-11.93 -3.852 5.034 
+-12.52 -3.546 4.548 
+-12.87 -4.803 5.622 
+-12.58 -5.09 4.606 
+-13.49 -4.516 4.767 
+-13.11 -6.264 5.38 
+-14.78 -6.803 5.643 
+-14.49 -7.092 4.622 
+-15.35 -8.042 5.637 
+-14.73 -8.43 5.528 
+-15.15 -8.236 4.95 
+-15.78 -9.378 5.503 
+-15.77 -9.385 5.497 
+-15.78 -9.375 5.495 
+-15.78 -9.378 5.486 
+-15.77 -9.383 5.484 
+-1.522 -2.262 -1.24 
+-1.519 -2.258 -1.231 
+-1.522 -2.262 -1.222 
+-1.529 -2.27 -1.222 
+-1.529 -2.27 -1.24 
+-2.061 -1.082 -0.8906 
+-2.428 -1.536 -1.907 
+-3.082 -0.4963 -0.5522 
+-3.082 -0.4963 -1.91 
+-3.759 -1.333 -1.628 
+-5.567 0.1257 -0.8323 
+-5.665 1.852 -0.8818 
+-6.417 0.9227 -0.8818 
+-6.041 1.387 -1.924 
+-6.95 2.279 -1.137 
+-6.937 1.957 -1.326 
+-6.943 2.118 -1.418 
+-7.378 0.9683 -0.9246 
+-8.108 1.724 -0.9246 
+-7.743 1.346 -1.84 
+-8.797 0.8371 -0.6052 
+-9.793 0.269 -1.611 
+-8.891 -0.6654 -1.611 
+-10.59 -2.11 -0.9326 
+-10.57 -0.523 -0.8679 
+-11.3 -1.375 -0.9326 
+-10.94 -1.742 -1.823 
+-11.75 -2.506 -1.223 
+-11.73 -2.523 -1.223 
+-11.74 -2.514 -1.247 
+-12.76 -3.466 -1.017 
+-12.14 -3.852 -1.017 
+-12.45 -3.659 -1.656 
+-13.16 -4.803 -0.6001 
+-12.7 -5.09 -1.55 
+-13.62 -4.516 -1.55 
+-13.36 -6.264 -0.8809 
+-15.05 -6.803 -0.9114 
+-14.58 -7.092 -1.866 
+-15.6 -8.042 -1.016 
+-14.98 -8.43 -1.016 
+-15.29 -8.236 -1.658 
+-16.01 -9.378 -1.222 
+-15.99 -9.385 -1.226 
+-16.01 -9.375 -1.231 
+-16.01 -9.378 -1.24 
+-16 -9.383 -1.24 
+-1.522 -2.27 -4.918 
+-2.105 -1.082 -4.684 
+-2.827 -1.989 -4.812 
+-1.513 -2.262 -4.935 
+-2.29 -1.536 -5.749 
+-4.562 -0.3933 -4.75 
+-4.55 -0.6204 -5.878 
+-6.395 0.9227 -5.432 
+-5.655 1.852 -5.302 
+-5.844 1.387 -6.393 
+-6.877 2.279 -5.776 
+-6.863 1.957 -5.773 
+-6.821 2.118 -6.051 
+-7.747 1.346 -5.408 
+-7.335 0.9683 -5.641 
+-7.947 1.724 -6.372 
+-7.536 1.346 -6.605 
+-9.347 -0.1982 -5.543 
+-9.085 -0.1982 -7.025 
+-8.702 -0.7393 -6.193 
+-11.08 -1.528 -6.095 
+-10.49 -2.11 -6.206 
+-10.91 -1.528 -7.101 
+-10.39 -2.11 -6.794 
+-11.59 -2.509 -6.689 
+-11.57 -2.523 -6.691 
+-11.58 -2.509 -6.715 
+-11.57 -2.523 -6.707 
+-12.52 -3.546 -6.495 
+-12.01 -3.852 -6.559 
+-12.39 -3.546 -7.217 
+-13.09 -4.803 -6.326 
+-12.47 -5.09 -7.18 
+-13.38 -4.516 -7.341 
+-13.24 -6.264 -6.637 
+-14.89 -6.803 -6.96 
+-14.27 -7.092 -7.819 
+-15.42 -8.042 -7.159 
+-14.8 -8.43 -7.051 
+-15 -8.236 -7.738 
+-15.78 -9.378 -7.432 
+-15.77 -9.385 -7.434 
+-15.78 -9.375 -7.442 
+-15.78 -9.378 -7.45 
+-15.77 -9.383 -7.448 
+1.522 -2.27 -4.918 
+1.511 -2.258 -4.926 
+1.513 -2.262 -4.935 
+2.828 -1.989 -4.812 
+2.105 -1.082 -4.684 
+2.29 -1.536 -5.749 
+4.55 -0.6204 -5.878 
+4.562 -0.3933 -4.75 
+6.395 0.9227 -5.432 
+5.655 1.852 -5.302 
+5.844 1.387 -6.393 
+6.877 2.279 -5.776 
+6.863 1.957 -5.773 
+6.821 2.118 -6.051 
+7.335 0.9683 -5.641 
+7.747 1.346 -5.408 
+7.947 1.724 -6.372 
+7.536 1.346 -6.605 
+9.347 -0.1982 -5.543 
+9.086 -0.1982 -7.025 
+8.702 -0.7393 -6.193 
+11.08 -1.528 -6.095 
+10.49 -2.11 -6.206 
+10.91 -1.528 -7.101 
+10.39 -2.11 -6.794 
+11.59 -2.509 -6.689 
+11.57 -2.523 -6.691 
+11.58 -2.509 -6.715 
+11.57 -2.523 -6.707 
+12.52 -3.546 -6.495 
+12.01 -3.852 -6.559 
+12.39 -3.546 -7.217 
+12.47 -5.09 -7.18 
+13.09 -4.803 -6.326 
+13.38 -4.516 -7.341 
+13.24 -6.264 -6.637 
+14.89 -6.803 -6.96 
+14.27 -7.092 -7.819 
+15.42 -8.042 -7.159 
+14.8 -8.43 -7.051 
+15 -8.236 -7.738 
+15.78 -9.378 -7.432 
+15.77 -9.385 -7.434 
+15.78 -9.375 -7.442 
+15.78 -9.378 -7.45 
+15.77 -9.383 -7.448 
+-0.9592 -0.9547 10.35 
+0.007813 0.3928 11.6 
+-0.7324 1.062 10.63 
+0.007813 -1.855 11.37 
+0.007813 -2.459 10.63 
+0.007813 0.3928 9.662 
+-0.3928 1.509 10.63 
+0.7327 1.062 10.63 
+-0.007813 0.3928 11.6 
+0.9595 -0.9547 10.35 
+-0.007813 -1.855 11.37 
+-0.007813 -2.459 10.63 
+-0.007813 0.3928 9.662 
+0.3931 1.509 10.63 
+1.513 -2.262 2.988 
+1.511 -2.258 2.979 
+1.516 -2.262 2.97 
+1.522 -2.27 2.971 
+1.52 -2.27 2.989 
+1.987 -1.082 3.408 
+2.524 -1.536 2.471 
+2.933 -0.4963 3.919 
+3.168 -0.4963 2.581 
+3.786 -1.333 2.977 
+5.429 0.1257 4.074 
+5.534 1.852 4.042 
+6.274 0.9227 4.173 
+6.085 1.387 3.082 
+6.863 1.957 3.827 
+6.844 2.279 4.015 
+6.886 2.118 3.737 
+7.229 0.9683 4.298 
+7.947 1.724 4.425 
+7.747 1.346 3.46 
+8.57 0.8371 4.859 
+9.726 0.269 4.042 
+8.838 -0.6654 3.885 
+10.39 -2.11 4.847 
+10.37 -0.523 4.909 
+11.09 -1.375 4.97 
+10.89 -1.742 4.032 
+11.59 -2.506 4.763 
+11.57 -2.523 4.76 
+11.58 -2.514 4.739 
+12.55 -3.466 5.142 
+11.93 -3.852 5.034 
+12.35 -3.659 4.459 
+12.58 -5.09 4.606 
+12.87 -4.803 5.622 
+13.49 -4.516 4.767 
+13.11 -6.264 5.38 
+14.78 -6.803 5.643 
+14.49 -7.092 4.622 
+15.35 -8.042 5.637 
+14.73 -8.43 5.528 
+15.15 -8.236 4.95 
+15.78 -9.378 5.503 
+15.77 -9.385 5.497 
+15.78 -9.375 5.495 
+15.78 -9.378 5.486 
+15.77 -9.383 5.484 
+1.529 -2.27 -1.222 
+1.519 -2.258 -1.231 
+1.522 -2.262 -1.24 
+2.795 -1.989 -0.8906 
+2.062 -1.082 -0.8906 
+2.428 -1.536 -1.907 
+4.677 -0.6204 -1.642 
+4.493 -0.3933 -0.5283 
+6.417 0.9227 -0.8818 
+5.665 1.852 -0.8818 
+6.041 1.387 -1.924 
+6.951 2.279 -1.137 
+6.937 1.957 -1.137 
+6.944 2.118 -1.418 
+7.379 0.9683 -0.9246 
+7.743 1.346 -0.623 
+8.108 1.724 -1.538 
+7.743 1.346 -1.84 
+9.343 -0.1982 -0.4792 
+9.343 -0.1982 -1.983 
+8.82 -0.7393 -1.231 
+11.15 -1.528 -0.7207 
+10.59 -2.11 -0.9326 
+11.15 -1.528 -1.742 
+10.59 -2.11 -1.53 
+11.75 -2.509 -1.218 
+11.73 -2.523 -1.223 
+11.75 -2.509 -1.245 
+11.73 -2.523 -1.239 
+12.63 -3.546 -0.8647 
+12.14 -3.852 -1.017 
+12.63 -3.546 -1.598 
+12.7 -5.09 -1.55 
+13.16 -4.803 -0.6001 
+13.62 -4.516 -1.55 
+13.36 -6.264 -0.8804 
+15.05 -6.803 -0.9111 
+14.58 -7.092 -1.866 
+15.6 -8.042 -1.016 
+14.98 -8.43 -1.016 
+15.29 -8.236 -1.658 
+16.01 -9.378 -1.222 
+15.99 -9.385 -1.226 
+16.01 -9.375 -1.231 
+16.01 -9.378 -1.24 
+16 -9.383 -1.24 
+-0.7932 4.462 -7.734 
+-0.3843 1.974 -5.495 
+1.95 3.241 -7.348 
+1.167 0.6428 -6.109 
+3.808 0.1871 -9.572 
+3.644 1.688 -11.88 
+0.07617 4.961 -10.12 
+3.28 -0.5704 -14.15 
+0.2488 -1.848 -16.78 
+-0.9744 -2.686 -16.57 
+0.7307 -3.159 -16.47 
+-2.678 2.963 -8.185 
+-2.616 -2.779 -12.24 
+-1.159 -1.533 -8.922 
+3 0 1 2 
+3 1 3 2 
+3 2 4 5 
+3 4 6 5 
+3 5 6 7 
+3 7 6 8 
+3 2 3 9 
+3 2 9 4 
+3 4 9 6 
+3 6 9 8 
+3 5 0 2 
+3 5 7 0 
+3 8 10 7 
+3 7 10 0 
+3 0 10 1 
+3 1 10 11 
+3 1 11 3 
+3 10 12 11 
+3 11 12 3 
+3 3 12 9 
+3 10 8 12 
+3 12 8 9 
+3 13 14 15 
+3 15 14 16 
+3 17 15 16 
+3 18 19 14 
+3 14 19 16 
+3 19 20 16 
+3 15 17 21 
+3 15 21 13 
+3 14 13 18 
+3 21 22 13 
+3 13 22 18 
+3 21 23 22 
+3 21 24 23 
+3 23 25 22 
+3 22 25 18 
+3 18 25 20 
+3 18 20 19 
+3 23 26 25 
+3 25 26 20 
+3 23 24 26 
+3 26 24 27 
+3 26 27 20 
+3 20 27 16 
+3 24 21 27 
+3 27 21 17 
+3 27 17 16 
+3 28 29 30 
+3 31 32 29 
+3 29 32 30 
+3 32 33 30 
+3 30 33 28 
+3 28 33 34 
+3 28 34 35 
+3 35 34 36 
+3 28 35 29 
+3 35 36 29 
+3 29 36 31 
+3 36 37 31 
+3 31 37 32 
+3 37 38 32 
+3 32 38 33 
+3 36 34 37 
+3 37 34 38 
+3 38 34 33 
+3 39 40 41 
+3 42 43 40 
+3 40 43 41 
+3 43 44 41 
+3 41 44 39 
+3 39 44 45 
+3 39 45 46 
+3 46 45 47 
+3 39 46 40 
+3 46 47 40 
+3 40 47 42 
+3 47 48 42 
+3 42 48 43 
+3 48 49 43 
+3 43 49 44 
+3 47 45 48 
+3 48 45 49 
+3 49 45 44 
+3 50 51 52 
+3 50 52 53 
+3 51 54 55 
+3 51 55 52 
+3 54 56 57 
+3 54 57 55 
+3 56 58 59 
+3 56 59 57 
+3 58 60 61 
+3 58 61 59 
+3 60 50 53 
+3 60 53 61 
+3 53 52 62 
+3 53 62 63 
+3 52 55 64 
+3 52 64 62 
+3 55 57 65 
+3 55 65 64 
+3 57 59 66 
+3 57 66 65 
+3 59 61 67 
+3 59 67 66 
+3 61 53 63 
+3 61 63 67 
+3 63 62 68 
+3 63 68 69 
+3 62 64 70 
+3 62 70 68 
+3 64 65 71 
+3 64 71 70 
+3 65 66 72 
+3 65 72 71 
+3 66 67 73 
+3 66 73 72 
+3 67 63 69 
+3 67 69 73 
+3 69 68 74 
+3 69 74 75 
+3 68 70 76 
+3 68 76 74 
+3 70 71 77 
+3 70 77 76 
+3 71 72 78 
+3 71 78 77 
+3 72 73 79 
+3 72 79 78 
+3 73 69 75 
+3 73 75 79 
+3 75 74 80 
+3 75 80 81 
+3 74 76 82 
+3 74 82 80 
+3 76 77 83 
+3 76 83 82 
+3 77 78 84 
+3 77 84 83 
+3 78 79 85 
+3 78 85 84 
+3 79 75 81 
+3 79 81 85 
+3 81 80 86 
+3 81 86 87 
+3 80 82 88 
+3 80 88 86 
+3 82 83 89 
+3 82 89 88 
+3 83 84 90 
+3 83 90 89 
+3 84 85 91 
+3 84 91 90 
+3 85 81 87 
+3 85 87 91 
+3 87 86 92 
+3 87 92 93 
+3 86 88 94 
+3 86 94 92 
+3 88 89 95 
+3 88 95 94 
+3 89 90 96 
+3 89 96 95 
+3 90 91 97 
+3 90 97 96 
+3 91 87 93 
+3 91 93 97 
+3 93 92 98 
+3 93 98 99 
+3 92 94 100 
+3 92 100 98 
+3 94 95 101 
+3 94 101 100 
+3 95 96 102 
+3 95 102 101 
+3 96 97 103 
+3 96 103 102 
+3 97 93 99 
+3 97 99 103 
+3 99 98 104 
+3 99 104 105 
+3 98 100 106 
+3 98 106 104 
+3 100 101 107 
+3 100 107 106 
+3 101 102 108 
+3 101 108 107 
+3 102 103 109 
+3 102 109 108 
+3 103 99 105 
+3 103 105 109 
+3 105 104 110 
+3 105 110 111 
+3 104 106 112 
+3 104 112 110 
+3 106 107 113 
+3 106 113 112 
+3 107 108 114 
+3 107 114 113 
+3 108 109 115 
+3 108 115 114 
+3 109 105 111 
+3 109 111 115 
+3 54 51 50 
+3 56 54 50 
+3 58 56 50 
+3 60 58 50 
+3 112 113 110 
+3 113 114 110 
+3 114 115 110 
+3 115 111 110 
+3 116 117 118 
+3 119 116 118 
+3 120 121 117 
+3 116 120 117 
+3 122 123 121 
+3 120 122 121 
+3 124 125 123 
+3 122 124 123 
+3 126 127 125 
+3 124 126 125 
+3 119 118 127 
+3 126 119 127 
+3 128 116 119 
+3 129 128 119 
+3 130 120 116 
+3 128 130 116 
+3 131 122 120 
+3 130 131 120 
+3 132 124 122 
+3 131 132 122 
+3 133 126 124 
+3 132 133 124 
+3 129 119 126 
+3 133 129 126 
+3 134 128 129 
+3 135 134 129 
+3 136 130 128 
+3 134 136 128 
+3 137 131 130 
+3 136 137 130 
+3 138 132 131 
+3 137 138 131 
+3 139 133 132 
+3 138 139 132 
+3 135 129 133 
+3 139 135 133 
+3 140 134 135 
+3 141 140 135 
+3 142 136 134 
+3 140 142 134 
+3 143 137 136 
+3 142 143 136 
+3 144 138 137 
+3 143 144 137 
+3 145 139 138 
+3 144 145 138 
+3 141 135 139 

+ 165 - 0
test/models-nonbsd/PLY/ant-half.ply.license

@@ -0,0 +1,165 @@
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

BIN
test/models/BLEND/BlenderDefault_271.blend


File diff suppressed because it is too large
+ 7561 - 0
test/models/Collada/anims_with_full_rotations_between_keys.DAE


+ 95 - 0
test/models/OpenGEX/Example.ogex

@@ -0,0 +1,95 @@
+Metric (key = "distance") {float {1}}
+Metric (key = "angle") {float {1}}
+Metric (key = "time") {float {1}}
+Metric (key = "up") {string {"z"}}
+
+GeometryNode $node1
+{
+	Name {string {"Box001"}}
+	ObjectRef {ref {$geometry1}}
+	MaterialRef {ref {$material1}}
+
+	Transform
+	{
+		float[16]
+		{
+			{0x3F800000, 0x00000000, 0x00000000, 0x00000000,		// {1, 0, 0, 0
+			 0x00000000, 0x3F800000, 0x00000000, 0x00000000,		//  0, 1, 0, 0
+			 0x00000000, 0x00000000, 0x3F800000, 0x00000000,		//  0, 0, 1, 0
+			 0xBEF33B00, 0x411804DE, 0x00000000, 0x3F800000}		//  -0.47506, 9.50119, 0, 1}
+		}
+	}
+}
+
+GeometryNode $node2
+{
+	Name {string {"Box002"}}
+	ObjectRef {ref {$geometry1}}
+	MaterialRef {ref {$material1}}
+
+	Transform
+	{
+		float[16]
+		{
+			{0x3F800000, 0x00000000, 0x00000000, 0x00000000,		// {1, 0, 0, 0
+			 0x00000000, 0x3F800000, 0x00000000, 0x00000000,		//  0, 1, 0, 0
+			 0x00000000, 0x00000000, 0x3F800000, 0x00000000,		//  0, 0, 1, 0
+			 0x43041438, 0x411804DE, 0x00000000, 0x3F800000}		//  132.079, 9.50119, 0, 1}
+		}
+	}
+}
+
+GeometryObject $geometry1		// Box001, Box002
+{
+	Mesh (primitive = "triangles")
+	{
+		VertexArray (attrib = "position")
+		{
+			float[3]		// 24
+			{
+				{0xC2501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0x424C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x42BA3928},
+				{0xC2501375, 0xC24C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x42BA3928}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x42BA3928},
+				{0x42501375, 0x424C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x42BA3928}, {0x42501375, 0x424C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x42BA3928}
+			}
+		}
+
+		VertexArray (attrib = "normal")
+		{
+			float[3]		// 24
+			{
+				{0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000},
+				{0x00000000, 0xBF800000, 0x00000000}, {0x00000000, 0xBF800000, 0x00000000}, {0x00000000, 0xBF800000, 0x00000000}, {0x80000000, 0xBF800000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000},
+				{0x00000000, 0x3F800000, 0x00000000}, {0x00000000, 0x3F800000, 0x00000000}, {0x00000000, 0x3F800000, 0x00000000}, {0x80000000, 0x3F800000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}
+			}
+		}
+
+		VertexArray (attrib = "texcoord")
+		{
+			float[2]		// 24
+			{
+				{0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000},
+				{0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000},
+				{0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}
+			}
+		}
+
+		IndexArray
+		{
+			unsigned_int32[3]		// 12
+			{
+				{0, 1, 2}, {2, 3, 0}, {4, 5, 6}, {6, 7, 4}, {8, 9, 10}, {10, 11, 8}, {12, 13, 14}, {14, 15, 12}, {16, 17, 18}, {18, 19, 16}, {20, 21, 22}, {22, 23, 20}
+			}
+		}
+	}
+}
+
+Material $material1
+{
+	Name {string {"03 - Default"}}
+
+	Color (attrib = "diffuse") {float[3] {{0.588235, 0.588235, 0.588235}}}
+	Texture (attrib = "diffuse")
+	{
+		string {"texture/Concrete.tga"}
+	}
+}

+ 50 - 52
test/regression/README

@@ -3,83 +3,81 @@ Assimp Regression Test Suite
 
 
 1) How does it work?
 1) How does it work?
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
-run.py checks all model in the <root>/test/models folder and compares the result
-against a regression database provided by us (db.zip). If the test passes
-successfully, Assimp definitely WORKS perfectly on your system. A few failures
-are totally fine as well (see sections 7+). You need to worry if a huge
-majority of all files in a particular format or post-processing configuration 
-fails - this might be a sign of a recent regression in assimp's codebase. 
+run.py checks all model in the <root>/test/models* folders and compares the result
+against a regression database provided with assimp (db.zip). A few failures
+are totally fine (see sections 7+). You need to worry if a huge
+majority of all files in a particular format (or post-processing configuration)
+fails as this might be a sign of a recent regression in assimp's codebase or
+gross incompatibility with your system or compiler. 
 
 
 2) What do I need?
 2) What do I need?
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
- - you need Python installed - 3.x !!
- - you need to build tools/assimp_cmd as described in the INSTALL file (
-	make && make install on unixes,release-dll target with msvc).
+ - You need Python installed (2.7+, 3.x). On Windows, run the scripts using "py".
+ - You need to build the assimp command line tool (ASSIMP_BUILD_ASSIMP_TOOLS
+   CMake build flag). Both run.py and gen_db.py take the full path to the binary
+   as first command line parameter.
 
 
 3) How to add more test files?
 3) How to add more test files?
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
 Use the following procedure:
 Use the following procedure:
- - verify the correctness of your assimp build - run the regression suite.
-   DO NOT continue if one or more tests fail.
- - add your additional test files to <root>/test/models/<fileformat>, where
-   <fileformat> is the file type (typically the file extension)
- - rebuild the regression database using gen_db.py
- - run the regression suite again - all tests should pass, including
-   those for the new files.
-
- - contributors: commit the db.zip plus your additional test files to
-   the SVN repository. 
-
-4) I made a change/fix/.. to a loader, how to update the database?
+ - Verify the correctness of your assimp build - run the regression suite.
+   DO NOT continue if more tests fail than usual.
+ - Add your additional test files to <root>/test/models/<fileformat>, where
+   <fileformat> is the file type (typically the file extension).
+ - If you test file does not meet the BSD license requirements, add it to
+   <root>/test/models-nonbsd/<fileformat> so people know to be careful with it.
+ - Rebuild the regression database:
+   "gen_db.py <binary> -ixyz" where .xyz is the file extension of the new file.
+ - Run the regression suite again. There should be no new failures and the new
+   file should not be among the failures.
+ - Include the db.zip file with your Pull Request. Travis CI enforces a passing
+   regression suite (with offenders whitelisted as a last resort).
+
+4) I made a change/fix/patch to a loader, how to update the database?
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
- - rebuild the regression database using gen_db.py
- - run the suite - all tests should pass now. If they do not, don't continue
- 
- - contributors: commit the db.zip to the SVN repository 
-
-5) How to add my whole model repository to the suite?
+ - Rebuild the regression database using "gen_db.py <binary> -ixyz"
+   where .xyz is the file extension for which the loader was patched.
+ - Run the regression suite again. There should be no new failures and the new
+   file should not be among the failures.
+ - Include the db.zip file with your Pull Request. Travis CI enforces a passing
+   regression suite (with offenders whitelisted as a last resort).
+
+5) How to add my whole model repository to the database?
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
 
 
 Edit the reg_settings.py file and add the path to your repository to
 Edit the reg_settings.py file and add the path to your repository to
-<<model_directories>>. Then, rebuild the suite.
+<<model_directories>>. Then, rebuild the database.
 
 
-6) So what is actually verified?
+6) So what is actually tested?
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
-The regression database includes mini dumps of the aiScene data structure -
+The regression database includes mini dumps of the aiScene data structure, i.e.
 the scene hierarchy plus the sizes of all data arrays MUST match. Floating-point
 the scene hierarchy plus the sizes of all data arrays MUST match. Floating-point
-data buffers, such as vertex positions, are handled less strictly: min,max and
-average values are stored with lower precision. This takes hardware- or 
+data buffers, such as vertex positions are handled less strictly: min, max and
+average values are stored with low precision. This takes hardware- or 
 compiler-specific differences in floating-point computations into account. 
 compiler-specific differences in floating-point computations into account. 
 Generally, almost all significant regressions will be detected while the
 Generally, almost all significant regressions will be detected while the
 number of false positives is relatively low.
 number of false positives is relatively low.
 
 
 7) The test suite fails, what do do?
 7) The test suite fails, what do do?
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
-Get back to ../results and check out regression_suite_failures.txt 
-It contains a list of all files which failed the test ... they're copied to
-../results/tmp. Both an EXPECTED and an ACTUAL file is produced per test.
-The output of `assimp cmpdump` is written to regressions_suite_output.txt. 
-To quickly find all all reports pertaining to tests which failed, I'd
-recommend grepping for 'but' because its a constituent of all error messages
-produced by assimp_cmd :) Error reports contain detailed information
-regarding the point of failure inside the data structure, the values of
-the two corresponding fields that were found to be different from EXPECTED
-and ACTUAL, respectively, ... this should offer you enough information to start
-debugging.
+Get back to <root>/test/results and look at regression_suite_failures.txt.
+It contains a list of all files which failed the test. Failing dumps are copied to
+root>/test/results/tmp. Both an EXPECTED and an ACTUAL file is produced per test.
+The output of "assimp cmpdump" is written to regressions_suite_output.txt. Grep
+for the file name in question and locate the log for the failed comparison. It
+contains a full trace of which scene elements have been compared before, which
+makes it reasonably easy to locate the offending field.
 
 
 8) fp:fast vs fp:precise fails the test suite (same for gcc equivalents)
 8) fp:fast vs fp:precise fails the test suite (same for gcc equivalents)
 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------
 As mentioned above, floating-point inaccuracies between differently optimized
 As mentioned above, floating-point inaccuracies between differently optimized
 builds are not considered regressions and all float comparisons done by the test
 builds are not considered regressions and all float comparisons done by the test
-suite involve an epsilon. Changing floating-point optimizations can, however,
- lead to *real* changes in the output data structure, such as different number 
-of vertices or faces, ... this violates one of our primary targets, that is
-produce reliable and portable output. We're working hard on removing these
-issues, but at the moment you have to live with few of them.
-
-Currently, the regression database is build on Windows using MSVC8 with 
-fp:precise. This leads to a small number of failures with fp:fast and
-virtally every build with gcc. Be patient, it will be fixed.
+suite involve an epsilon to accomodate. However compiler settings that allow
+compilers to perform non-IEEE754 compliant optimizations can cause arbitrary
+failures in the test suite. Even if the compiler is configured to be IEE754
+comformant, there is lots of code in assimp that leaves the compiler a choice
+and different compilers make different choices (for example the precision of
+float intermediaries is implementation-specified).
 
 
 
 
 
 

BIN
test/regression/db.zip


+ 17 - 15
test/regression/gen_db.py

@@ -69,6 +69,9 @@ configs for an IDE, make sure to build the assimp_cmd project.
 
 
 -i,--include: List of file extensions to update dumps for. If omitted,
 -i,--include: List of file extensions to update dumps for. If omitted,
          all file extensions are updated except those in `exclude`.
          all file extensions are updated except those in `exclude`.
+         Example: -ixyz,abc
+                  -i.xyz,.abc
+                  --include=xyz,abc
 
 
 -e,--exclude: Merged with settings.exclude_extensions to produce a
 -e,--exclude: Merged with settings.exclude_extensions to produce a
          list of all file extensions to ignore. If dumps exist,
          list of all file extensions to ignore. If dumps exist,
@@ -78,8 +81,6 @@ configs for an IDE, make sure to build the assimp_cmd project.
          Dont' change anything.
          Dont' change anything.
 
 
 -n,--nozip: Don't pack to ZIP archive. Keep all dumps in individual files.
 -n,--nozip: Don't pack to ZIP archive. Keep all dumps in individual files.
-
-(lists of file extensions are comma delimited, i.e. `3ds,lwo,x`)
 """
 """
 
 
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------
@@ -164,7 +165,7 @@ def gen_db(ext_list,outfile):
     num = 0
     num = 0
     for tp in settings.model_directories:
     for tp in settings.model_directories:
         num += process_dir(tp, outfile,
         num += process_dir(tp, outfile,
-            lambda x: os.path.splitext(x)[1] in ext_list)
+            lambda x: os.path.splitext(x)[1].lower() in ext_list and not x in settings.files_to_ignore)
 
 
     print("="*60)
     print("="*60)
     print("Updated {0} entries".format(num))
     print("Updated {0} entries".format(num))
@@ -172,43 +173,44 @@ def gen_db(ext_list,outfile):
 
 
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------
 if __name__ == "__main__":
 if __name__ == "__main__":
-    assimp_bin_path = sys.argv[1] if len(sys.argv) > 1 else 'assimp'
-
     def clean(f):
     def clean(f):
         f = f.strip("* \'")
         f = f.strip("* \'")
         return "."+f if f[:1] != '.' else f
         return "."+f if f[:1] != '.' else f
 
 
-    if len(sys.argv)>1 and (sys.argv[1] == "--help" or sys.argv[1] == "-h"):
+    if len(sys.argv) <= 1 or sys.argv[1] == "--help" or sys.argv[1] == "-h":
         print(usage)
         print(usage)
         sys.exit(0)
         sys.exit(0)
 
 
+    assimp_bin_path = sys.argv[1]    
     ext_list, preview, nozip = None, False, False
     ext_list, preview, nozip = None, False, False
-    for m in sys.argv[1:]:
+    for m in sys.argv[2:]:
         if m[:10]=="--exclude=":
         if m[:10]=="--exclude=":
             settings.exclude_extensions += map(clean, m[10:].split(","))
             settings.exclude_extensions += map(clean, m[10:].split(","))
-        elif m[:3]=="-e=":
-            settings.exclude_extensions += map(clean, m[3:].split(","))
+        elif m[:2]=="-e":
+            settings.exclude_extensions += map(clean, m[2:].split(","))
         elif m[:10]=="--include=":
         elif m[:10]=="--include=":
             ext_list = m[10:].split(",")
             ext_list = m[10:].split(",")
-        elif m[:3]=="-i=":
-            ext_list = m[3:].split(",")
+        elif m[:2]=="-i":
+            ext_list = m[2:].split(",")
         elif m=="-p" or m == "--preview":
         elif m=="-p" or m == "--preview":
             preview = True
             preview = True
         elif m=="-n" or m == "--nozip":
         elif m=="-n" or m == "--nozip":
             nozip = True
             nozip = True
+        else:
+            print("Unrecognized parameter: " + m)
+            sys.exit(-1)
             
             
     outfile = open(os.path.join("..", "results", "gen_regression_db_output.txt"), "w")
     outfile = open(os.path.join("..", "results", "gen_regression_db_output.txt"), "w")
     if ext_list is None:
     if ext_list is None:
         (ext_list, err) = subprocess.Popen([assimp_bin_path, "listext"],
         (ext_list, err) = subprocess.Popen([assimp_bin_path, "listext"],
             stdout=subprocess.PIPE).communicate()
             stdout=subprocess.PIPE).communicate()
-        ext_list = str(ext_list).lower().split(";")
+        ext_list = str(ext_list.strip()).lower().split(";")
 
 
     # todo: Fix for multi dot extensions like .skeleton.xml
     # todo: Fix for multi dot extensions like .skeleton.xml
     ext_list = list(filter(lambda f: not f in settings.exclude_extensions,
     ext_list = list(filter(lambda f: not f in settings.exclude_extensions,
         map(clean, ext_list)))
         map(clean, ext_list)))
-
-    if preview:
-        print(','.join(ext_list))
+    print('File extensions processed: ' + ', '.join(ext_list))
+    if preview:       
         sys.exit(1)
         sys.exit(1)
 
 
     extract_zip()    
     extract_zip()    

+ 22 - 18
test/regression/run.py

@@ -65,7 +65,7 @@ import utils
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------
 EXPECTED_FAILURE_NOT_MET, DATABASE_LENGTH_MISMATCH, \
 EXPECTED_FAILURE_NOT_MET, DATABASE_LENGTH_MISMATCH, \
 DATABASE_VALUE_MISMATCH, IMPORT_FAILURE, \
 DATABASE_VALUE_MISMATCH, IMPORT_FAILURE, \
-FILE_NOT_READABLE, COMPARE_SUCCESS = range(6)
+FILE_NOT_READABLE, COMPARE_SUCCESS, EXPECTED_FAILURE = range(7)
 
 
 messages = collections.defaultdict(lambda: "<unknown", {
 messages = collections.defaultdict(lambda: "<unknown", {
         EXPECTED_FAILURE_NOT_MET:
         EXPECTED_FAILURE_NOT_MET:
@@ -88,7 +88,10 @@ messages = collections.defaultdict(lambda: "<unknown", {
 
 
         COMPARE_SUCCESS:
         COMPARE_SUCCESS:
 """Results match archived reference dump in database\n\
 """Results match archived reference dump in database\n\
-\tNumber of bytes compared: {0}"""
+\tNumber of bytes compared: {0}""",
+
+        EXPECTED_FAILURE:
+"""Expected failure was met.""",
 })
 })
 
 
 outfilename_output = "run_regression_suite_output.txt"
 outfilename_output = "run_regression_suite_output.txt"
@@ -167,11 +170,11 @@ def process_dir(d, outfile_results, zipin, result):
     print("Processing directory " + d)
     print("Processing directory " + d)
     for f in sorted(os.listdir(d)):
     for f in sorted(os.listdir(d)):
         fullpath = os.path.join(d, f)
         fullpath = os.path.join(d, f)
-        if os.path.isdir(fullpath) and not f == ".svn":
+        if os.path.isdir(fullpath) and not f[:1] == '.':
             process_dir(fullpath, outfile_results, zipin, result)
             process_dir(fullpath, outfile_results, zipin, result)
             continue
             continue
 
 
-        if f in settings.files_to_ignore:
+        if f in settings.files_to_ignore or os.path.splitext(f)[1] in settings.exclude_extensions:
             print("Ignoring " + f)
             print("Ignoring " + f)
             continue
             continue
 
 
@@ -190,32 +193,30 @@ def process_dir(d, outfile_results, zipin, result):
                     "regression database? Use gen_db.zip to re-generate.")
                     "regression database? Use gen_db.zip to re-generate.")
                 continue
                 continue
 
 
-            # Ignore extensions via settings.py configured list
-            # todo: Fix for multi dot extensions like .skeleton.xml
-            ext = os.path.splitext(fullpath)[1].lower()
-            if ext != "" and ext in settings.exclude_extensions:
-                continue
-
             print("-"*60 + "\n  " + os.path.realpath(fullpath) + " pp: " + pppreset) 
             print("-"*60 + "\n  " + os.path.realpath(fullpath) + " pp: " + pppreset) 
             
             
             outfile_actual = prepare_output_dir(fullpath, filehash, "ACTUAL")
             outfile_actual = prepare_output_dir(fullpath, filehash, "ACTUAL")
             outfile_expect = prepare_output_dir(fullpath, filehash, "EXPECT")
             outfile_expect = prepare_output_dir(fullpath, filehash, "EXPECT")
             outfile_results.write("assimp dump    "+"-"*80+"\n")
             outfile_results.write("assimp dump    "+"-"*80+"\n")
             outfile_results.flush()
             outfile_results.flush()
-
             command = [assimp_bin_path,
             command = [assimp_bin_path,
                 "dump",
                 "dump",
                 fullpath, outfile_actual, "-b", "-s", "-l" ] +\
                 fullpath, outfile_actual, "-b", "-s", "-l" ] +\
                 pppreset.split()
                 pppreset.split()
-
             r = subprocess.call(command, **shellparams)
             r = subprocess.call(command, **shellparams)
-            print(r)
+            outfile_results.flush()
 
 
             if r and not failure:
             if r and not failure:
                 result.fail(fullpath, outfile_expect, pppreset, IMPORT_FAILURE, r)
                 result.fail(fullpath, outfile_expect, pppreset, IMPORT_FAILURE, r)
+                outfile_results.write("Failed to import\n")
                 continue
                 continue
             elif failure and not r:
             elif failure and not r:
                 result.fail(fullpath, outfile_expect, pppreset, EXPECTED_FAILURE_NOT_MET)
                 result.fail(fullpath, outfile_expect, pppreset, EXPECTED_FAILURE_NOT_MET)
+                outfile_results.write("Expected import to fail\n")
+                continue
+            elif failure and r:
+                result.ok(fullpath, pppreset, EXPECTED_FAILURE) 
+                outfile_results.write("Failed as expected, skipping.\n")
                 continue
                 continue
             
             
             with open(outfile_expect, "wb") as s:
             with open(outfile_expect, "wb") as s:
@@ -227,21 +228,24 @@ def process_dir(d, outfile_results, zipin, result):
             except IOError:
             except IOError:
                 continue
                 continue
                 
                 
+            outfile_results.write("Expected data length: {0}\n".format(len(input_expected)))
+            outfile_results.write("Actual data length: {0}\n".format(len(input_actual)))
+            failed = False
             if len(input_expected) != len(input_actual):
             if len(input_expected) != len(input_actual):
                 result.fail(fullpath, outfile_expect, pppreset, DATABASE_LENGTH_MISMATCH,
                 result.fail(fullpath, outfile_expect, pppreset, DATABASE_LENGTH_MISMATCH,
                         len(input_expected), len(input_actual))
                         len(input_expected), len(input_actual))
-                continue
+                # Still compare the dumps to see what the difference is
+                failed = True
 
 
             outfile_results.write("assimp cmpdump "+"-"*80+"\n")
             outfile_results.write("assimp cmpdump "+"-"*80+"\n")
             outfile_results.flush()
             outfile_results.flush()
-
             command = [ assimp_bin_path, 'cmpdump', outfile_actual, outfile_expect ]
             command = [ assimp_bin_path, 'cmpdump', outfile_actual, outfile_expect ]
             if subprocess.call(command, **shellparams) != 0:
             if subprocess.call(command, **shellparams) != 0:
-                result.fail(fullpath, outfile_expect, pppreset, DATABASE_VALUE_MISMATCH)
+                if not failed:
+                    result.fail(fullpath, outfile_expect, pppreset, DATABASE_VALUE_MISMATCH)
                 continue 
                 continue 
             
             
-            result.ok(fullpath, pppreset, COMPARE_SUCCESS, 
-                len(input_expected))     
+            result.ok(fullpath, pppreset, COMPARE_SUCCESS, len(input_expected))     
 
 
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------
 def del_folder_with_contents(folder):
 def del_folder_with_contents(folder):

+ 2 - 2
test/regression/settings.py

@@ -60,9 +60,9 @@ files_to_ignore = ["pond.0.ply"]
 # File extensions are case insensitive
 # File extensions are case insensitive
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------
 exclude_extensions = [
 exclude_extensions = [
-    ".lws", ".assbin", ".assxml", ".txt", ".md",
+    ".assbin", ".assxml", ".txt", ".md",
     ".jpeg", ".jpg", ".png", ".gif", ".tga", ".bmp",
     ".jpeg", ".jpg", ".png", ".gif", ".tga", ".bmp",
-    ".skeleton", ".skeleton.xml"
+    ".skeleton", ".skeleton.xml", ".license", ".mtl", ".material"
 ]
 ]
 
 
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------

+ 2 - 4
test/regression/utils.py

@@ -50,15 +50,13 @@ def hashing(file,pp):
     needs to be persistent across different python implementations
     needs to be persistent across different python implementations
     and platforms, so we implement the hashing manually.
     and platforms, so we implement the hashing manually.
     """
     """
-
+    file = file.lower()
     file = file.replace('\\','/')+":"+pp
     file = file.replace('\\','/')+":"+pp
     # SDBM hash
     # SDBM hash
     res = 0
     res = 0
     for t in file:
     for t in file:
         res = (ord(t) + (res<<6) + (res<<16) - res) % 2**32
         res = (ord(t) + (res<<6) + (res<<16) - res) % 2**32
-
-    # Python 2.7 normalization: strip 'L' suffix.
-    return hex(res).rstrip('L')
+    return '{:x}'.format(res)
 
 
 
 
  # vim: ai ts=4 sts=4 et sw=4
  # vim: ai ts=4 sts=4 et sw=4

+ 1 - 1
tools/assimp_cmd/CMakeLists.txt

@@ -28,7 +28,7 @@ IF( WIN32 )
 		MAIN_DEPENDENCY assimp)
 		MAIN_DEPENDENCY assimp)
 ENDIF( WIN32 )
 ENDIF( WIN32 )
 
 
-TARGET_LINK_LIBRARIES( assimp_cmd assimp ${ZLIB_LIBRARIES})
+TARGET_LINK_LIBRARIES( assimp_cmd assimp ${ZLIB_LIBRARIES} )
 SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES
 SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES
 	OUTPUT_NAME assimp
 	OUTPUT_NAME assimp
 )
 )

+ 37 - 14
tools/assimp_cmd/CompareDump.cpp

@@ -140,15 +140,16 @@ public:
 		if(it != history.back().second.end()) {
 		if(it != history.back().second.end()) {
 			++history.back().second[s];
 			++history.back().second[s];
 		}
 		}
-		else history.back().second[s] = 1;
+		else history.back().second[s] = 0;
 
 
 		history.push_back(HistoryEntry(s,PerChunkCounter()));
 		history.push_back(HistoryEntry(s,PerChunkCounter()));
-
+		debug_trace.push_back("PUSH " + s);
 	}
 	}
 
 
 	/* leave current scope */
 	/* leave current scope */
 	void pop_elem() {
 	void pop_elem() {
 		ai_assert(history.size());
 		ai_assert(history.size());
+		debug_trace.push_back("POP "+ history.back().first);
 		history.pop_back();
 		history.pop_back();
 	}
 	}
 
 
@@ -249,30 +250,50 @@ private:
 		const char* last = history.back().first.c_str();
 		const char* last = history.back().first.c_str();
 		std::string pad;
 		std::string pad;
 
 
-		for(ChunkHistory::reverse_iterator rev = ++history.rbegin(),
-			end = history.rend(); rev < end; ++rev, pad += "  ")
+		for(ChunkHistory::reverse_iterator rev = history.rbegin(),
+			end = history.rend(); rev != end; ++rev, pad += "  ")
 		{
 		{
-			ss << pad << (*rev).first << "(Index: " << (*rev).second[last]-1 << ")" << std::endl;
+			ss << pad << (*rev).first << "(Index: " << (*rev).second[last] << ")" << std::endl;
 			last = (*rev).first.c_str();
 			last = (*rev).first.c_str();
 		}
 		}
 
 
+		ss << std::endl << "Debug trace: "<< std::endl;
+		for (std::vector<std::string>::const_iterator it = debug_trace.begin(); it != debug_trace.end(); ++it) {
+			ss << *it << std::endl;
+		}
 		return ss.str();
 		return ss.str();
 	}
 	}
 
 
 
 
-	/* read from both streams simult.*/
+	/* read from both streams at the same time */
 	template <typename T> void read(T& filla,T& fille) {
 	template <typename T> void read(T& filla,T& fille) {
 		if(1 != fread(&filla,sizeof(T),1,actual)) {
 		if(1 != fread(&filla,sizeof(T),1,actual)) {
-			throw compare_fails_exception("Unexpected EOF reading ACTUAL");
+			EOFActual();
 		}
 		}
 		if(1 != fread(&fille,sizeof(T),1,expect)) {
 		if(1 != fread(&fille,sizeof(T),1,expect)) {
-			throw compare_fails_exception("Unexpected EOF reading EXPECT");
+			EOFExpect();
 		}
 		}
 	}
 	}
 
 
-
 private:
 private:
 
 
+	void EOFActual() {
+		std::stringstream ss;
+		throw compare_fails_exception((ss
+			<< "Unexpected EOF reading ACTUAL.\nCurrent position in scene hierarchy is "
+			<< print_hierarchy(),ss.str().c_str()
+			));
+	}
+
+	void EOFExpect() {
+		std::stringstream ss;
+		throw compare_fails_exception((ss
+			<< "Unexpected EOF reading EXPECT.\nCurrent position in scene hierarchy is "
+			<< print_hierarchy(),ss.str().c_str()
+			));
+	}
+
+
 	FILE *const actual, *const expect;
 	FILE *const actual, *const expect;
 
 
 	typedef std::map<std::string,unsigned int> PerChunkCounter;
 	typedef std::map<std::string,unsigned int> PerChunkCounter;
@@ -281,6 +302,8 @@ private:
 	typedef std::deque<HistoryEntry> ChunkHistory;
 	typedef std::deque<HistoryEntry> ChunkHistory;
 	ChunkHistory history;
 	ChunkHistory history;
 
 
+	std::vector<std::string> debug_trace;
+
 	typedef std::stack<std::pair<uint32_t,uint32_t> > LengthStack;
 	typedef std::stack<std::pair<uint32_t,uint32_t> > LengthStack;
 	LengthStack lengths;
 	LengthStack lengths;
 
 
@@ -296,10 +319,10 @@ template <> void comparer_context :: read<aiString>(aiString& filla,aiString& fi
 	read(lena,lene);
 	read(lena,lene);
 
 
 	if(lena && 1 != fread(&filla.data,lena,1,actual)) {
 	if(lena && 1 != fread(&filla.data,lena,1,actual)) {
-		throw compare_fails_exception("Unexpected EOF reading ACTUAL");
+		EOFActual();
 	}
 	}
 	if(lene && 1 != fread(&fille.data,lene,1,expect)) {
 	if(lene && 1 != fread(&fille.data,lene,1,expect)) {
-		throw compare_fails_exception("Unexpected EOF reading ACTUAL");
+		EOFExpect();
 	}
 	}
 
 
 	fille.data[fille.length=static_cast<unsigned int>(lene)] = '\0';
 	fille.data[fille.length=static_cast<unsigned int>(lene)] = '\0';
@@ -493,7 +516,7 @@ private:
 		res|=fread(&actual.second,4,1,ctx.get_actual())		<<3u;
 		res|=fread(&actual.second,4,1,ctx.get_actual())		<<3u;
 
 
 		if(res!=0xf) {
 		if(res!=0xf) {
-			ctx.failure("I/OError reading chunk head, dumps are not well-defined","<ChunkHead>");
+			ctx.failure("IO Error reading chunk head, dumps are malformed","<ChunkHead>");
 		}
 		}
 
 
 		if (current.first != actual.first) {
 		if (current.first != actual.first) {
@@ -510,7 +533,7 @@ private:
 		if (current.first != actual.first) {
 		if (current.first != actual.first) {
 			std::stringstream ss;
 			std::stringstream ss;
 			ctx.failure((ss
 			ctx.failure((ss
-				<<"Chunk lenghts do not match. EXPECT: "
+				<<"Chunk lengths do not match. EXPECT: "
 				<<current.second
 				<<current.second
 				<<" ACTUAL: " 
 				<<" ACTUAL: " 
 				<< actual.second,
 				<< actual.second,
@@ -729,7 +752,7 @@ void CompareOnTheFlyLight(comparer_context& comp)	{
 	const aiLightSourceType type = static_cast<aiLightSourceType>( 
 	const aiLightSourceType type = static_cast<aiLightSourceType>( 
 		comp.cmp<uint32_t>("mType"));
 		comp.cmp<uint32_t>("mType"));
 
 
-	if(type==aiLightSource_DIRECTIONAL) {
+	if(type!=aiLightSource_DIRECTIONAL) {
 		comp.cmp<float>("mAttenuationConstant");
 		comp.cmp<float>("mAttenuationConstant");
 		comp.cmp<float>("mAttenuationLinear");
 		comp.cmp<float>("mAttenuationLinear");
 		comp.cmp<float>("mAttenuationQuadratic");
 		comp.cmp<float>("mAttenuationQuadratic");

+ 124 - 0
workspaces/Android-NDK/jni/Android.mk

@@ -0,0 +1,124 @@
+LOCAL_PATH := $(call my-dir)/../../../
+
+include $(CLEAR_VARS)
+LOCAL_MODULE    := assimp_static
+ASSIMP_SRC_DIR = code
+
+FILE_LIST := $(wildcard $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/*.cpp)
+FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/openddlparser/code/*.cpp)
+FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/unzip/*.c)
+FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/poly2tri/poly2tri/*/*.cc)
+
+LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
+
+LOCAL_SRC_FILES += contrib/clipper/clipper.cpp \
+	contrib/ConvertUTF/ConvertUTF.c \
+	contrib/irrXML/irrXML.cpp
+
+# enables -frtti and -fexceptions
+LOCAL_CPP_FEATURES := exceptions
+# identifier 'nullptr' will become a keyword in C++0x [-Wc++0x-compat]
+# but next breaks blender and other importer
+# LOCAL_CFLAGS += -std=c++11
+  
+# cant be disabled? rudamentary function?
+#       -DASSIMP_BUILD_NO_FLIPWINDING_PROCESS  \
+#
+DontBuildProcess = \
+        -DASSIMP_BUILD_NO_FLIPUVS_PROCESS  \
+        -DASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS \
+        -DASSIMP_BUILD_NO_CALCTANGENTS_PROCESS \
+        -DASSIMP_BUILD_NO_DEBONE_PROCESS \
+        -DASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS \
+        -DASSIMP_BUILD_NO_FINDINSTANCES_PROCESS \
+        -DASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS \
+        -DASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS \
+        -DASSIMP_BUILD_NO_GENFACENORMALS_PROCESS \
+        -DASSIMP_BUILD_NO_GENUVCOORDS_PROCESS \
+        -DASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS \
+        -DASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS \
+        -DASSIMP_BUILD_NO_JOINVERTICES_PROCESS \
+        -DASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS \
+        -DASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS \
+        -DASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS \
+        -DASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS \
+        -DASSIMP_BUILD_NO_REMOVEVC_PROCESS \
+        -DASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS \
+        -DASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS \
+        -DASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS \
+        -DASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS \
+        -DASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS \
+        -DASSIMP_BUILD_NO_TRIANGULATE_PROCESS \
+        -DASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+
+DontBuildImporters = \
+        -DASSIMP_BUILD_NO_X_IMPORTER \
+        -DASSIMP_BUILD_NO_3DS_IMPORTER \
+        -DASSIMP_BUILD_NO_MD3_IMPORTER \
+        -DASSIMP_BUILD_NO_MDL_IMPORTER \
+        -DASSIMP_BUILD_NO_MD2_IMPORTER \
+        -DASSIMP_BUILD_NO_PLY_IMPORTER \
+        -DASSIMP_BUILD_NO_ASE_IMPORTER \
+        -DASSIMP_BUILD_NO_HMP_IMPORTER \
+        -DASSIMP_BUILD_NO_SMD_IMPORTER \
+        -DASSIMP_BUILD_NO_MDC_IMPORTER \
+        -DASSIMP_BUILD_NO_MD5_IMPORTER \
+        -DASSIMP_BUILD_NO_STL_IMPORTER \
+        -DASSIMP_BUILD_NO_LWO_IMPORTER \
+        -DASSIMP_BUILD_NO_DXF_IMPORTER \
+        -DASSIMP_BUILD_NO_NFF_IMPORTER \
+        -DASSIMP_BUILD_NO_RAW_IMPORTER \
+        -DASSIMP_BUILD_NO_OFF_IMPORTER \
+        -DASSIMP_BUILD_NO_AC_IMPORTER \
+        -DASSIMP_BUILD_NO_BVH_IMPORTER \
+        -DASSIMP_BUILD_NO_IRRMESH_IMPORTER \
+        -DASSIMP_BUILD_NO_IRR_IMPORTER \
+        -DASSIMP_BUILD_NO_Q3D_IMPORTER \
+        -DASSIMP_BUILD_NO_B3D_IMPORTER \
+        -DASSIMP_BUILD_NO_COLLADA_IMPORTER \
+        -DASSIMP_BUILD_NO_TERRAGEN_IMPORTER \
+        -DASSIMP_BUILD_NO_CSM_IMPORTER \
+        -DASSIMP_BUILD_NO_3D_IMPORTER \
+        -DASSIMP_BUILD_NO_LWS_IMPORTER \
+        -DASSIMP_BUILD_NO_OGRE_IMPORTER \
+        -DASSIMP_BUILD_NO_MS3D_IMPORTER \
+        -DASSIMP_BUILD_NO_COB_IMPORTER \
+        -DASSIMP_BUILD_NO_Q3BSP_IMPORTER \
+        -DASSIMP_BUILD_NO_NDO_IMPORTER \
+        -DASSIMP_BUILD_NO_IFC_IMPORTER \
+        -DASSIMP_BUILD_NO_XGL_IMPORTER \
+        -DASSIMP_BUILD_NO_FBX_IMPORTER \
+        -DASSIMP_BUILD_NO_C4D_IMPORTER \
+	-DASSIMP_BUILD_NO_OPENGEX_IMPORTER \
+        -DASSIMP_BUILD_NO_ASSBIN_IMPORTER
+#        -DASSIMP_BUILD_NO_BLEND_IMPORTER \
+#         -DASSIMP_BUILD_NO_GEO_IMPORTER
+#         -DASSIMP_BUILD_NO_OBJ_IMPORTER \
+#
+DontBuildImporters := -DASSIMP_BUILD_NO_IFC_IMPORTER -DASSIMP_BUILD_NO_IRRMESH_IMPORTER  -DASSIMP_BUILD_NO_IRR_IMPORTER -DASSIMP_BUILD_NO_C4D_IMPORTER
+
+ASSIMP_FLAGS_3_0 = -DASSIMP_BUILD_DLL_EXPORT -DASSIMP_BUILD_NO_OWN_ZLIB -DASSIMP_BUILD_BOOST_WORKAROUND -Dassimp_EXPORTS -fPIC -fvisibility=hidden -Wall
+ASSIMP_FLAGS_3_1 = $(ASSIMP_FLAGS_3_0) # -DASSIMP_BUILD_BLENDER_DEBUG
+
+LOCAL_CFLAGS += $(ASSIMP_FLAGS_3_1) -DASSIMP_BUILD_NO_EXPORT -DOPENDDL_NO_USE_CPP11 $(DontBuildImporters)  # $(DontBuildProcess) 
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround $(LOCAL_PATH)/contrib/openddlparser/include ./ 
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE    := assimp
+
+LOCAL_CFLAGS += -UASSIMP_BUILD_DLL_EXPORT
+LOCAL_WHOLE_STATIC_LIBRARIES = assimp_static
+
+LOCAL_LDLIBS := -lz
+
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround
+include $(BUILD_SHARED_LIBRARY)
+
+-include $(LOCAL_PATH)/assimp_cmd.mk
+
+# let it on original place
+include $(LOCAL_PATH)/port/jassimp/jassimp-native/Android.mk

+ 8 - 0
workspaces/Android-NDK/jni/Application.mk

@@ -0,0 +1,8 @@
+ifeq ($(CC),clang)
+    NDK_TOOLCHAIN_VERSION := $(CC)
+    $(info "Use llvm Compiler")
+endif
+
+APP_ABI := armeabi-v7a
+
+APP_STL := stlport_static

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