Parcourir la source

Merge remote-tracking branch 'origin'

Conflicts:
	code/C4DImporter.cpp
	code/OgreImporter.h
abma il y a 10 ans
Parent
commit
8c45a4dc3b
95 fichiers modifiés avec 26953 ajouts et 4528 suppressions
  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
 bin/
 lib/
-contrib/
+
 
 # Generated
 assimp.pc
@@ -54,3 +54,7 @@ tools/assimp_view/assimp_viewer.vcxproj.user
 
 # 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:
+  - sudo apt-get update -qq
   - 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:
-    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=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
 
@@ -19,19 +25,22 @@ compiler:
   - clang
 
 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:
-  - 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 )
 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
 set (ASSIMP_VERSION_MAJOR 3)
 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")
 
+add_definitions( -DOPENDDL_NO_USE_CPP11 )
+
 # Get the current working branch
 execute_process(
     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")
 
-# 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
 IF (NOT TARGET uninstall)
     # add make uninstall capability

+ 5 - 0
CREDITS

@@ -151,3 +151,8 @@ Ogre Binary format support
 
 - Filip Wasil, Tieto Poland Sp. z o.o.
 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 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 ####
 
-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
-- BLEND (Blender 3D)
+- BLEND (Blender)
 - DAE/Collada
 - FBX
 - IFC-STEP 
@@ -46,13 +53,13 @@ The library provides importers for a lot of file formats, including:
 - Ogre Binary
 - Ogre XML
 - 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)
 
-Exporters include:
+__Exporters__:
 
 - DAE (Collada)
 - STL
@@ -63,23 +70,21 @@ Exporters include:
 - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
 - 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 ####
 
 
-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
 	/contrib	Third-party libraries
 	/doc		Documentation (doxysource and pre-compiled docs)
 	/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
 	/port		Ports to other languages and scripts to maintain those.
 	/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!)
 
 
-
-### 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 ###
 
 
 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).
 
-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) 
 
 ### 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 
 a pull request with your changes against the main repository's `master` branch.
 
-
 ### 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 - 
 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
-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"));
 	if(!outfile) {
@@ -191,8 +191,8 @@ Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, c
 
 	{
 		ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
-		WriteMeshes();
 		WriteMaterials();
+		WriteMeshes();
 
 		{
 			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;
 	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
 
-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" );
 	if (!out) return;

+ 17 - 1
code/BlenderIntermediate.h

@@ -123,6 +123,16 @@ namespace Blender {
 #ifdef _MSC_VER
 #	pragma warning(disable:4351)
 #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
 	 *  the various ConvertXXX routines in BlenderImporter.*/
@@ -135,7 +145,13 @@ namespace Blender {
 			, 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, 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 (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());
+				ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name)-2);
 				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->specr = p->specg = p->specb = 0.6f;
 				p->ambr = p->ambg = p->ambb = 0.0f;
 				p->mirr = p->mirg = p->mirb = 0.0f;
 				p->emit = 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() );
 				conv_data.materials_raw.push_back(p);
-
-				LogInfo("Adding default material ...");
+				LogInfo("Adding default material");
 			}
 			mesh->mMaterialIndex = index;
 		}
@@ -593,6 +595,7 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 	
 		aiMaterial* mout = new aiMaterial();
 		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
 		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)
 {
 	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;
 		if (object->parent == obj) {
 			children.push_back(object);

+ 2 - 0
code/BlobIOSystem.h

@@ -129,9 +129,11 @@ public:
 		{
 		case aiOrigin_CUR:
 			cursor += pOffset;
+			break;
 
 		case aiOrigin_END:
 			cursor = file_size - pOffset;
+			break;
 
 		case aiOrigin_SET:
 			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
  *  @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
 // 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})
 
-
-
 SET( MD2_SRCS
 	MD2FileData.h
 	MD2Loader.cpp
@@ -361,6 +359,13 @@ SET( 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
 	PlyLoader.cpp
 	PlyLoader.h
@@ -636,6 +641,17 @@ SET( 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
 if(MSVC10)
@@ -691,6 +707,7 @@ SET( assimp_src
 	${OFFFormat_SRCS}
 	${Obj_SRCS}
 	${Ogre_SRCS}
+    ${OpenGEX_SRCS}
 	${Ply_SRCS}
 	${Q3D_SRCS}
 	${Q3BSP_SRCS}
@@ -715,6 +732,7 @@ SET( assimp_src
 	${unzip_compile_SRCS}
 	${Poly2Tri_SRCS}
 	${Clipper_SRCS}
+    ${openddl_parser_SRCS}
 	# Necessary to show the headers in the project when using the VC++ generator:
 	${Boost_SRCS}
 
@@ -722,6 +740,11 @@ SET( assimp_src
 	${COMPILER_HEADERS}
 
 )
+add_definitions( -DOPENDDLPARSER_BUILD )
+
+INCLUDE_DIRECTORIES( 
+    ../contrib/openddlparser/include
+)
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 	SET( assimp_src ${assimp_src} ${C4D_SRCS})
@@ -730,7 +753,7 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 
 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)
 	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));
-	void (COBImporter::* load)(Scene&,StreamReaderLE*)= head[15]=='A'?&COBImporter::ReadAsciiFile:&COBImporter::ReadBinaryFile;
 	if (head[16]!='L') {
 		ThrowException("File is big-endian, which is not supported");
 	}
 	
 	// 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()) {
 		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
-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 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. */
 struct Material
 {
+	std::string mName;
 	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, -1,  0,  0,
 				 0,  0,  0,  1);
-        }
+		}
 	// store all meshes
 	StoreSceneMeshes( pScene);
 
@@ -1385,7 +1385,7 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 
 		// create material
 		aiMaterial* mat = new aiMaterial;
-		aiString name( matIt->first);
+		aiString name( material.mName.empty() ? matIt->first : material.mName );
 		mat->AddProperty(&name,AI_MATKEY_NAME);
 
 		// store the material

+ 41 - 7
code/ColladaParser.cpp

@@ -66,7 +66,7 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
 {
 	mRootNode = NULL;
 	mUnitSize = 1.0f;
-	mUpDirection = UP_Z;
+	mUpDirection = UP_Y;
 
 	// We assume the newest file format by default
 	mFormat = FV_1_5_n;
@@ -231,10 +231,10 @@ void ColladaParser::ReadAssetInfo()
 				const char* content = GetTextContent();
 				if( strncmp( content, "X_UP", 4) == 0)
 					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;
+				else
+					mUpDirection = UP_Y;
 
 				// check element end
 				TestClosing( "up_axis");
@@ -823,6 +823,7 @@ void ColladaParser::ReadMaterialLibrary()
 	if( mReader->isEmptyElement())
 		return;
 
+	std::map<std::string, int> names;
 	while( mReader->read())
 	{
 		if( mReader->getNodeType() == irr::io::EXN_ELEMENT) 
@@ -833,8 +834,32 @@ void ColladaParser::ReadMaterialLibrary()
 				int attrID = GetAttribute( "id");
 				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
-				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
 			{
 				// ignore the rest
@@ -1391,6 +1416,9 @@ void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler)
 				if( attrTex >= 0 )
 	  				pSampler.mUVChannel = mReader->getAttributeValue( attrTex);
 				//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"))
 			{
@@ -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
 					actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType);
 				}
+			}
+			else if (IsElement("extra"))
+			{
+				SkipElement("extra");
 			} else
 			{
 				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);
+	}
+#endif
 
 	// only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
 	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
 // 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
@@ -97,7 +97,7 @@ Exporter::ExportFormatEntry gExporters[] =
 	Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
 #endif
 
-#ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER
+#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
 	Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
 		aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
 #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) {
 		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();
 
@@ -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
 	// this, however. To avoid surprises and bug reports, we check for duplicates in
 	// 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 = "";
 	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());
 				}
 
-				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) {
 				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

+ 124 - 34
code/FBXConverter.cpp

@@ -1971,9 +1971,12 @@ private:
 
 		// strip AnimationStack:: prefix
 		std::string name = st.Name();
-		if(name.substr(0,16) == "AnimationStack::") {
+		if (name.substr(0, 16) == "AnimationStack::") {
 			name = name.substr(16);
 		}
+		else if (name.substr(0, 11) == "AnimStack::") {
+			name = name.substr(11);
+		}
 
 		anim->mName.Set(name);
 		
@@ -2017,12 +2020,18 @@ private:
 		double min_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 {
 			BOOST_FOREACH(const NodeMap::value_type& kv, node_map) {
 				GenerateNodeAnimations(node_anims, 
 					kv.first, 
 					kv.second, 
 					layer_map, 
+					start_time, stop_time,
 					max_time, 
 					min_time);
 			}
@@ -2046,9 +2055,27 @@ private:
 			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
 		// 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;
 	}
 
@@ -2058,6 +2085,7 @@ private:
 		const std::string& fixed_name, 
 		const std::vector<const AnimationCurveNode*>& curves, 
 		const LayerMap& layer_map, 
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& min_time)
 	{
@@ -2150,13 +2178,19 @@ private:
 			aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain, 
 				node_property_map.end(), 
 				layer_map,
+				start, stop,
 				max_time,
 				min_time,
 				true // input is TRS order, assimp is SRT
 				);
 
 			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;
 		}
 
@@ -2188,6 +2222,7 @@ private:
 						target, 
 						(*chain[i]).second,
 						layer_map,
+						start, stop,
 						max_time,
 						min_time);
 
@@ -2203,6 +2238,7 @@ private:
 						target, 
 						(*chain[i]).second,
 						layer_map,
+						start, stop,
 						max_time,
 						min_time);
 
@@ -2215,12 +2251,18 @@ private:
 							target, 
 							(*chain[i]).second,
 							layer_map,
+							start, stop,
 							max_time,
 							min_time,
 							true);
 
 						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);
 						flags |= bit << (TransformationComp_RotationPivotInverse - i);
@@ -2233,12 +2275,18 @@ private:
 							target, 
 							(*chain[i]).second,
 							layer_map,
+							start, stop,
 							max_time,
 							min_time,
 							true);
 
 						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);
 						flags |= bit << (TransformationComp_RotationPivotInverse - i);
@@ -2252,6 +2300,7 @@ private:
 						target, 
 						(*chain[i]).second,
 						layer_map,
+						start, stop,
 						max_time,
 						min_time);
 
@@ -2262,7 +2311,12 @@ private:
 				}
 
 				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;
 			}
 		}
@@ -2323,13 +2377,14 @@ private:
 		const Model& target, 
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& min_time)
 	{
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		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
 		na->mScalingKeys = new aiVectorKey[1];
@@ -2354,13 +2409,14 @@ private:
 		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& min_time)
 	{
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		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
 		na->mRotationKeys = new aiQuatKey[1];
@@ -2385,6 +2441,7 @@ private:
 		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& min_time,
 		bool inverse = false)
@@ -2392,7 +2449,7 @@ private:
 		ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
 		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) {
 			for (unsigned int i = 0; i < na->mNumPositionKeys; ++i) {
@@ -2425,6 +2482,7 @@ private:
 		NodeMap::const_iterator chain[TransformationComp_MAXIMUM], 
 		NodeMap::const_iterator iter_end,
 		const LayerMap& layer_map,
+		int64_t start, int64_t stop,
 		double& max_time,
 		double& min_time,
 		bool reverse_order = false)
@@ -2446,21 +2504,21 @@ private:
 			KeyFrameListList rotation;
 			
 			if(chain[TransformationComp_Scaling] != iter_end) {
-				scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second);
+				scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop);
 			}
 			else {
 				def_scale = PropertyGet(props,"Lcl Scaling",aiVector3D(1.f,1.f,1.f));
 			}
 
 			if(chain[TransformationComp_Translation] != iter_end) {
-				translation = GetKeyframeList((*chain[TransformationComp_Translation]).second);
+				translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop);
 			}
 			else {
 				def_translate = PropertyGet(props,"Lcl Translation",aiVector3D(0.f,0.f,0.f));
 			}
 			
 			if(chain[TransformationComp_Rotation] != iter_end) {
-				rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second);
+				rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop);
 			}
 			else {
 				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_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
 			// likely produce if not all three channels were equally dense.
@@ -2510,6 +2571,7 @@ private:
 			if(chain[TransformationComp_Scaling] != iter_end) {
 				ConvertScaleKeys(na, (*chain[TransformationComp_Scaling]).second, 
 					layer_map, 
+					start, stop,
 					max_time, 
 					min_time);
 			}
@@ -2525,6 +2587,7 @@ private:
 			if(chain[TransformationComp_Rotation] != iter_end) {
 				ConvertRotationKeys(na, (*chain[TransformationComp_Rotation]).second, 
 					layer_map, 
+					start, stop,
 					max_time,
 					min_time,
 					target.RotationOrder());
@@ -2542,6 +2605,7 @@ private:
 			if(chain[TransformationComp_Translation] != iter_end) {
 				ConvertTranslationKeys(na, (*chain[TransformationComp_Translation]).second, 
 					layer_map, 
+					start, stop,
 					max_time, 
 					min_time);
 			}
@@ -2561,17 +2625,21 @@ private:
 
 
 	// 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;
 
 	
 
 	// ------------------------------------------------------------------------------------------------
-	KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes)
+	KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop)
 	{
 		KeyFrameListList inputs;
 		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) {
 			ai_assert(node);
 
@@ -2596,7 +2664,23 @@ private:
 				const AnimationCurve* const curve = kv.second;
 				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 :-)
@@ -2626,7 +2710,7 @@ private:
 		const size_t count = inputs.size();
 		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) {
 				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;
 			}
 			keys.push_back(min_tick);
@@ -2835,6 +2919,7 @@ private:
 
 	// ------------------------------------------------------------------------------------------------
 	void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
+		int64_t start, int64_t stop,
 		double& maxTime,
 		double& minTime)
 	{
@@ -2844,36 +2929,40 @@ private:
 		// layers should be multiplied with each other). There is a FBX 
 		// 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);
 
 		na->mNumScalingKeys = static_cast<unsigned int>(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, 
 		const LayerMap& /*layers*/,
+		int64_t start, int64_t stop,
 		double& maxTime,
 		double& minTime)
 	{
 		ai_assert(nodes.size());
 
 		// XXX see notes in ConvertScaleKeys()
-		const KeyFrameListList& inputs = GetKeyframeList(nodes);
+		const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop);
 		const KeyTimeList& keys = GetKeyTimeList(inputs);
 
 		na->mNumPositionKeys = static_cast<unsigned int>(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, 
 		const LayerMap& /*layers*/,
+		int64_t start, int64_t stop,
 		double& maxTime,
 		double& minTime,
 		Model::RotOrder order)
@@ -2881,12 +2970,13 @@ private:
 		ai_assert(nodes.size());
 
 		// 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);
 
 		na->mNumRotationKeys = static_cast<unsigned int>(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;
 };
 
-typedef std::vector<uint64_t> KeyTimeList;
+typedef std::vector<int64_t> KeyTimeList;
 typedef std::vector<float> KeyValueList;
 
 /** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
@@ -1026,10 +1026,10 @@ 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)
 {
@@ -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)
@@ -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
 } // !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);
 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);
 
 
@@ -215,6 +216,7 @@ uint64_t ParseTokenAsID(const Token& t);
 size_t ParseTokenAsDim(const Token& t);
 float ParseTokenAsFloat(const Token& t);
 int ParseTokenAsInt(const Token& t);
+int64_t ParseTokenAsInt64(const Token& t);
 std::string ParseTokenAsString(const Token& t);
 
 /* 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<unsigned int>& out, const Element& el);
 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")) {
 		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]));
 	}
+	else if (!strcmp(cs, "KTime")) {
+		return new TypedProperty<int64_t>(ParseTokenAsInt64(*tok[4]));
+	}
 	else if (!strcmp(cs,"Vector3D") || 
 		!strcmp(cs,"ColorRGB") || 
 		!strcmp(cs,"Vector") || 
@@ -105,7 +108,7 @@ Property* ReadTypedProperty(const Element& element)
 			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 NULL;

+ 13 - 0
code/GenericProperty.h

@@ -111,5 +111,18 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
 		*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

+ 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));
 
 	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;
-	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));
 	}
 }

+ 95 - 76
code/IFCGeometry.cpp

@@ -523,43 +523,23 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
 	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;
 	}
 
-	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
 	IfcMatrix4 trafo;
@@ -567,7 +547,7 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
 
 	IfcVector3 vmin, vmax;
 	MinMaxChooser<IfcVector3>()(vmin, vmax);
-	BOOST_FOREACH(IfcVector3& v,in) {
+	BOOST_FOREACH(IfcVector3& v, in) {
 		v *= trafo;
 
 		vmin = std::min(vmin, v);
@@ -576,93 +556,91 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
 
 	vmax -= vmin;
 	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
-	IfcVector3 profileNormal = TempMesh::ComputePolygonNormal( in.data(), in.size());
+	IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(in.data(), in.size());
 	if( profileNormal * dir < 0.0 )
-		std::reverse( in.begin(), in.end());
+		std::reverse(in.begin(), in.end());
 
 	std::vector<IfcVector3> nors;
 	const bool openings = !!conv.apply_openings && conv.apply_openings->size();
-	
+
 	// Compute the normal vectors for all opening polygons as a prerequisite
 	// to TryAddOpenings_Poly2Tri()
 	// 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	 
 			// doesn't matter, but we would screw up if we started with e.g. a door in between	 
 			// 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());
-		BOOST_FOREACH(TempOpening& t,*conv.apply_openings) {
+		BOOST_FOREACH(TempOpening& t, *conv.apply_openings) {
 			TempMesh& bounds = *t.profileMesh.get();
-		
-			if (bounds.verts.size() <= 2) {
+
+			if( bounds.verts.size() <= 2 ) {
 				nors.push_back(IfcVector3());
 				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& curmesh = openings ? temp : result;
 	std::vector<IfcVector3>& out = curmesh.verts;
- 
+
 	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);
-		
+
 		out.push_back(in[i]);
 		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;
 			}
-			
+
 			result.Append(temp);
 			temp.Clear();
 		}
 	}
 
-	if(openings) {
+	if( openings ) {
 		BOOST_FOREACH(TempOpening& opening, *conv.apply_openings) {
-			if (!opening.wallPoints.empty()) {
+			if( !opening.wallPoints.empty() ) {
 				IFCImporter::LogError("failed to generate all window caps");
 			}
 			opening.wallPoints.clear();
 		}
 	}
-	
+
 	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 ) {
-				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]);
 			}
 
-			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;
 				}
 
@@ -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");
 	}
 
@@ -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
 	// 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);
 		boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
 		profile->Swap(result);
 
 		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());
-	} 
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+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();
 
 	if(fix_orientation) {
-		meshtmp->FixupFaceOrientation();
+//		meshtmp->FixupFaceOrientation();
 	}
 
 	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();
 
 	// skip over space and annotation nodes - usually, these have no meaning in Assimp's context
+	bool skipGeometry = false;
 	if(conv.settings.skipSpaceRepresentations) {
 		if(const IfcSpace* const space = el.ToPtr<IfcSpace>()) {
 			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;
 		}
 
-		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()) {
 			nd->mChildren = new aiNode*[subnodes.size()]();

Fichier diff supprimé car celui-ci est trop grand
+ 1091 - 1464
code/IFCReaderGen.cpp


Fichier diff supprimé car celui-ci est trop grand
+ 1278 - 1270
code/IFCReaderGen.h


+ 1 - 1
code/IFCUtil.cpp

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

+ 1 - 0
code/IFCUtil.h

@@ -277,6 +277,7 @@ IfcFloat ConvertSIPrefix(const std::string& prefix);
 
 // IFCProfile.cpp
 bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv);
+bool ProcessCurve(const IfcCurve& curve,  TempMesh& meshout, ConversionData& conv);
 
 // IFCMaterial.cpp
 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)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 All rights reserved.
 
@@ -140,6 +140,9 @@ corresponding preprocessor flag to selectively disable formats.
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 #	include "OgreImporter.h"
 #endif
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+#   include "OpenGEXImporter.h"
+#endif
 #ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
 #	include "MS3DLoader.h"
 #endif
@@ -177,132 +180,135 @@ namespace Assimp {
 // ------------------------------------------------------------------------------------------------
 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)
-	out.push_back( new XFileImporter());
+    out.push_back( new XFileImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
-	out.push_back( new ObjFileImporter());
+    out.push_back( new ObjFileImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
-	out.push_back( new Discreet3DSImporter());
+    out.push_back( new Discreet3DSImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
-	out.push_back( new MD3Importer());
+    out.push_back( new MD3Importer());
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
-	out.push_back( new MD2Importer());
+    out.push_back( new MD2Importer());
 #endif
 #if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
-	out.push_back( new PLYImporter());
+    out.push_back( new PLYImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
-	out.push_back( new MDLImporter());
+    out.push_back( new MDLImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
-	out.push_back( new ASEImporter());
+    out.push_back( new ASEImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
-	out.push_back( new HMPImporter());
+    out.push_back( new HMPImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
-	out.push_back( new SMDImporter());
+    out.push_back( new SMDImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
-	out.push_back( new MDCImporter());
+    out.push_back( new MDCImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
-	out.push_back( new MD5Importer());
+    out.push_back( new MD5Importer());
 #endif
 #if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
-	out.push_back( new STLImporter());
+    out.push_back( new STLImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
-	out.push_back( new LWOImporter());
+    out.push_back( new LWOImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
-	out.push_back( new DXFImporter());
+    out.push_back( new DXFImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
-	out.push_back( new NFFImporter());
+    out.push_back( new NFFImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
-	out.push_back( new RAWImporter());
+    out.push_back( new RAWImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
-	out.push_back( new OFFImporter());
+    out.push_back( new OFFImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
-	out.push_back( new AC3DImporter());
+    out.push_back( new AC3DImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
-	out.push_back( new BVHLoader());
+    out.push_back( new BVHLoader());
 #endif
 #if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
-	out.push_back( new IRRMeshImporter());
+    out.push_back( new IRRMeshImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
-	out.push_back( new IRRImporter());
+    out.push_back( new IRRImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
-	out.push_back( new Q3DImporter());
+    out.push_back( new Q3DImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
-	out.push_back( new B3DImporter());
+    out.push_back( new B3DImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
-	out.push_back( new ColladaLoader());
+    out.push_back( new ColladaLoader());
 #endif
 #if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
-	out.push_back( new TerragenImporter());
+    out.push_back( new TerragenImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
-	out.push_back( new CSMImporter());
+    out.push_back( new CSMImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
-	out.push_back( new UnrealImporter());
+    out.push_back( new UnrealImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
-	out.push_back( new LWSImporter());
+    out.push_back( new LWSImporter());
 #endif
 #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
 #if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
-	out.push_back( new MS3DImporter());
+    out.push_back( new MS3DImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
-	out.push_back( new COBImporter());
+    out.push_back( new COBImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
-	out.push_back( new BlenderImporter());
+    out.push_back( new BlenderImporter());
 #endif
 #if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
-	out.push_back( new Q3BSPFileImporter() );
+    out.push_back( new Q3BSPFileImporter() );
 #endif
 #if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
-	out.push_back( new NDOImporter() );
+    out.push_back( new NDOImporter() );
 #endif
 #if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
-	out.push_back( new IFCImporter() );
+    out.push_back( new IFCImporter() );
 #endif
 #if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
-	out.push_back( new XGLImporter() );
+    out.push_back( new XGLImporter() );
 #endif
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
-	out.push_back( new FBXImporter() );
+    out.push_back( new FBXImporter() );
 #endif
 #if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
-	out.push_back( new AssbinImporter() );
+    out.push_back( new AssbinImporter() );
 #endif
 
 #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
-	out.push_back( new C4DImporter() );
+    out.push_back( new C4DImporter() );
 #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
-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 
 	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 = {
-	"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;
@@ -75,99 +75,99 @@ using namespace std;
 // ------------------------------------------------------------------------------------------------
 //	Default constructor
 ObjFileImporter::ObjFileImporter() :
-	m_Buffer(),	
-	m_pRootObject( NULL ),
-	m_strAbsPath( "" )
+    m_Buffer(),	
+    m_pRootObject( NULL ),
+    m_strAbsPath( "" )
 {
     DefaultIOSystem io;
-	m_strAbsPath = io.getOsSeparator();
+    m_strAbsPath = io.getOsSeparator();
 }
 
 // ------------------------------------------------------------------------------------------------
 //	Destructor.
 ObjFileImporter::~ObjFileImporter()
 {
-	delete m_pRootObject;
-	m_pRootObject = NULL;
+    delete m_pRootObject;
+    m_pRootObject = NULL;
 }
 
 // ------------------------------------------------------------------------------------------------
 //	Returns true, if file is an obj file.
 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
 {
-	return &desc;
+    return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
 //	Obj-file import implementation
 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() ) {
         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 ) {
-		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 ) {
         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
 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 ) {
         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 ) {
         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 ) {
-			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
 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 ) {
         return NULL;
     }
 
-	// Create faces
-	ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
+    // Create faces
+    ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ meshIndex ];
     if( !pObjMesh ) {
         return NULL;
     }
     ai_assert( NULL != pObjMesh );
     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  );
 
-		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;
 }
@@ -359,335 +360,335 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
 // ------------------------------------------------------------------------------------------------
 //	Creates a vertex array
 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 );
-			}
-
-			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 
 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 
 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 
 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
 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
 {	
 public:
-	///	\brief	Default constructor
-	ObjFileImporter();
+    ///	\brief	Default constructor
+    ObjFileImporter();
 
-	///	\brief	Destructor
-	~ObjFileImporter();
+    ///	\brief	Destructor
+    ~ObjFileImporter();
 
 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:
 
-	//! \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,
-		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:
-	//!	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.
 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
-	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_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
 ObjFileParser::~ObjFileParser()
 {
-	delete m_pModel;
-	m_pModel = NULL;
+    delete m_pModel;
+    m_pModel = NULL;
 }
 
 // -------------------------------------------------------------------
 //	Returns a pointer to the model instance.
 ObjFile::Model *ObjFileParser::GetModel() const
 {
-	return m_pModel;
+    return m_pModel;
 }
 
 // -------------------------------------------------------------------
 //	File parsing method.
 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;
                                         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
 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 ) ) {
-		pBuffer[index] = *m_DataIt;
-		index++;
+        pBuffer[index] = *m_DataIt;
+        index++;
         if( index == length - 1 ) {
             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
 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
 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 );
     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
 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
 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 ) )
-		{
-			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
 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 ) ) {
         ++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
 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.
 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 ) {
         return;
     }
-	
-	char *pStart = &(*m_DataIt);
+    
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsLineEnd( *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.
 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 ) {
         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 ) ) {
         ++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 mat_index = -1;
+    int mat_index = -1;
     if( strMaterialName.empty() ) {
         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.  
 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 ) ) {
         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
 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
 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.
 void ObjFileParser::getObjectName()
 {
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
     if( m_DataIt == m_DataItEnd ) {
         return;
     }
-	char *pStart = &(*m_DataIt);
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *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 ) {
             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
 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
 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.
 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.
 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
 {
 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:
-	///	\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:
-	///	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 
     void getVector( std::vector<aiVector3D> &point3d_array );
     ///	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.
-	void getFace(aiPrimitiveType type);
-	/// Reads the material description.
+    void getFace(aiPrimitiveType type);
+    /// Reads the material description.
     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:
-	///	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

+ 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)
 {
 	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;
 	}
 

+ 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
-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 
 	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);
 }
 
-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 
 	PlyExporter exporter(pFile, pScene, true);

+ 46 - 27
code/PlyLoader.cpp

@@ -68,6 +68,25 @@ static const aiImporterDesc desc = {
 	"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
 PLYImporter::PLYImporter()
@@ -435,13 +454,13 @@ void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 				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])
 			{
 				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
 			pvOut->push_back(vOut);
@@ -545,19 +564,19 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 				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])
 			{
 				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])
 			{
 				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
@@ -663,28 +682,28 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 			
 			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])
 			{
-				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])
 			{
-				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
 			if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
 			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
@@ -777,11 +796,11 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				// parse the list of vertex indices
 				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);
 
 					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)
 					{
@@ -793,7 +812,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				if (0xFFFFFFFF != iMaterialIndex)
 				{
 					sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
-						(*i).alProperties[iMaterialIndex].avList.front(),eType2);
+						GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2);
 				}
 				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
 			bool flip = false;
 			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));
 
 				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;
 	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;
 	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;
 	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
 	if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
 	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
 			int iMode;
 			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
 				// become 1, not depending on the angle), use gouraud lighting
@@ -1047,7 +1066,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
 
 			// handle opacity
 			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);
 			}
 

+ 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
-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 
 	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);
 }
-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 
 	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;
 
 	// 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;
 
 	// ---------------------------------------------------------------------
@@ -571,6 +573,7 @@ void CatmullClarkSubdivider::InternSubdivide (
 			}
 		}
 	}
+	}  // end of scope for edges, freeing its memory
 
 	// ---------------------------------------------------------------------
 	// 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
-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 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 
-	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
 	boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
 	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.
@@ -103,7 +109,7 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce
 
 // ------------------------------------------------------------------------------------------------
 // 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
 	mOutput.imbue( std::locale("C") );
@@ -133,7 +139,7 @@ void XFileExporter::WriteFile()
 {
 	// note, that all realnumber values must be comma separated in x files
 	mOutput.setf(std::ios::fixed);
-	mOutput.precision(6); // precission for float
+	mOutput.precision(16); // precission for double
 
 	// entry of writing the file
 	WriteHeader();
@@ -155,7 +161,10 @@ void XFileExporter::WriteFile()
 // Writes the asset header
 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 << startstr << "template Frame {" << endstr;
 	PushTag();
@@ -305,7 +314,7 @@ void XFileExporter::WriteNode( aiNode* pNode)
 		ss << "Node_" << pNode;
 		pNode->mName.Set(ss.str());
 	}
-	mOutput << startstr << "Frame " << pNode->mName.C_Str() << " {" << endstr;
+	mOutput << startstr << "Frame " << toXFileString(pNode->mName) << " {" << endstr;
 
 	PushTag();
 
@@ -325,9 +334,9 @@ void XFileExporter::WriteNode( aiNode* pNode)
 	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();
 
@@ -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)
 {

+ 8 - 2
code/XFileExporter.h

@@ -66,7 +66,7 @@ class XFileExporter
 {
 public:
 	/// 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
 	virtual ~XFileExporter();
@@ -85,7 +85,7 @@ protected:
 	void WriteNode( aiNode* pNode );
 
 	/// 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
 	void PushTag() { startstr.append( "  "); }
@@ -99,6 +99,12 @@ public:
 
 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
 	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,
@@ -435,6 +435,12 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl
 		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
 	nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
 	if (nd->mNumMeshes) {

+ 11 - 0
code/XGLLoader.h

@@ -93,6 +93,7 @@ protected:
 
 private:
 
+	
 	struct TempScope
 	{
 		TempScope()
@@ -129,6 +130,16 @@ private:
 		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
 	{
 		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;
 }
 
+// ------------------------------------------------------------------------------------
+// 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.
 #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
 
 #include "cexport.h"
+#include <map>
 
 namespace Assimp	{
 	class ExporterPimpl;
@@ -72,6 +73,9 @@ namespace Assimp	{
  * #ExportToBlob is especially useful if you intend to work 
  * with the data in-memory. 
 */
+
+class ASSIMP_API ExportProperties;
+
 class ASSIMP_API Exporter
 	// TODO: causes good ol' base class has no dll interface warning
 //#ifdef __cplusplus
@@ -81,7 +85,7 @@ class ASSIMP_API Exporter
 public:
 
 	/** 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 */
 	struct ExportFormatEntry
@@ -171,8 +175,8 @@ public:
 	*   Any IO handlers set via #SetIOHandler are ignored here.
 	* @note Use aiCopyScene() to get a modifiable copy of a previously
 	*   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. 
 	 * @note Use aiCopyScene() to get a modifiable copy of a previously
 	 *   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

+ 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"
 
+
+// ---------- 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

+ 53 - 44
port/jassimp/build.xml

@@ -1,45 +1,54 @@
 <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 ANDROID
+#include <android/log.h>
+#define lprintf(...) __android_log_print(ANDROID_LOG_VERBOSE, __func__, __VA_ARGS__)
+#else
 #define lprintf(...) printf (__VA_ARGS__)
+#endif /* ANDROID */
 #else
 #define lprintf
 #endif
 
-
 static bool createInstance(JNIEnv *env, const char* className, jobject& newInstance)
 {
 	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);
+	env->DeleteLocalRef(clazz);
 
 	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);
 
@@ -60,6 +65,7 @@ static bool createInstance(JNIEnv *env, const char* className, const char* signa
 	}
 
 	newInstance = env->NewObjectA(clazz, ctr_id, params);
+	env->DeleteLocalRef(clazz);
 
 	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);
+	env->DeleteLocalRef(clazz);
 
 	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");
+	env->DeleteLocalRef(clazz);
 
 	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");
+	env->DeleteLocalRef(clazz);
 
 	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);
+	env->DeleteLocalRef(clazz);
 
 	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, 
-	const char* signature, const jvalue* params)
+	const char* signature,/* const*/ jvalue* params)
 {
 	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);
+	env->DeleteLocalRef(clazz);
 
 	if (NULL == mid)
 	{
@@ -210,6 +221,27 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
 		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);
 
 	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, 
-	const char* signature, const jvalue* params, jobject& returnValue)
+	const char* signature,/* const*/ jvalue* params, jobject& returnValue)
 {
 	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)
 	{
-		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;
 	}
 
@@ -283,7 +315,7 @@ static bool copyBufferArray(JNIEnv *env, jobject jMesh, const char* jBufferName,
 
 	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;
 	}
 
@@ -338,7 +370,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		/* set general mesh data in java */
 		jvalue setTypesParams[1];
 		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;
 		}
@@ -380,7 +412,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		allocateBuffersParams[1].i = cMesh->mNumFaces;
 		allocateBuffersParams[2].z = isPureTriangle;
 		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;
 		}
@@ -470,7 +502,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].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");
 				return false;
@@ -491,7 +523,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 1;
 			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");
 				return false;
@@ -512,7 +544,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 2;
 			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");
 				return false;
@@ -535,7 +567,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				jvalue allocateDataChannelParams[2];
 				allocateDataChannelParams[0].i = 3;
 				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");
 					return false;
@@ -574,7 +606,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				}
 
 				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");
 					return false;
@@ -671,7 +703,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapParams[0].l = jMatrixArr;
 				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;
 				}
@@ -701,6 +733,8 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				}
 			}
 		}
+		env->DeleteLocalRef(jMeshes);
+		env->DeleteLocalRef(jMesh);
 	}
 
 	return true;
@@ -719,7 +753,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
 	wrapMatParams[0].l = jMatrixArr;
 	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;
 	}
@@ -749,7 +783,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
 	wrapNodeParams[2].l = jMeshrefArr;
 	wrapNodeParams[3].l = jNodeName;
 	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)) 
 	{
 		return false;
@@ -805,7 +839,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 	{
 		const aiMaterial* cMaterial = cScene->mMaterials[m];
 
-		lprintf("converting material ...\n", m);
+		lprintf("converting material %d ...\n", m);
 
 		jobject jMaterial = NULL;
 
@@ -842,7 +876,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			setNumberParams[0].i = ttInd;
 			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;
 			}
@@ -880,7 +914,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapColorParams[0].f = ((float*) cProperty->mData)[0];
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				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;
 				}
@@ -905,7 +939,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
 				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;
 				}
@@ -1137,7 +1171,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorDiffuse.g;
 		wrapColorParams[2].f = cLight->mColorDiffuse.b;
 		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;
 		}
@@ -1146,7 +1180,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorSpecular.g;
 		wrapColorParams[2].f = cLight->mColorSpecular.b;
 		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;
 		}
@@ -1155,7 +1189,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorAmbient.g;
 		wrapColorParams[2].f = cLight->mColorAmbient.b;
 		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;
 		}
@@ -1167,7 +1201,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		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;
 		}
@@ -1176,7 +1210,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		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;
 		}
@@ -1242,7 +1276,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mPosition.y;
 		wrapPositionParams[2].f = cCamera->mPosition.z;
 		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;
 		}
@@ -1251,7 +1285,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mUp.y;
 		wrapPositionParams[2].f = cCamera->mUp.z;
 		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;
 		}
@@ -1260,7 +1294,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mLookAt.y;
 		wrapPositionParams[2].f = cCamera->mLookAt.z;
 		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;
 		}
@@ -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
   (JNIEnv *env, jclass jClazz)
 {

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

@@ -7,6 +7,23 @@
 #ifdef __cplusplus
 extern "C" {
 #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
  * 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.
      */
-    private static final int SIZEOF_FLOAT = 4;
-    
-    
+    private static final int SIZEOF_FLOAT = Jassimp.NATIVE_FLOAT_SIZE;
+        
     /**
      * 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)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 All rights reserved.
 
@@ -68,19 +68,19 @@ import java.nio.ByteOrder;
  */
 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.
      */
-    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_postState = AiAnimBehavior.fromRawValue(postBehavior);
         
-        /* c data is padded -> 24 bytes with 20 bytes data */
         m_posKeys = ByteBuffer.allocateDirect(numPosKeys * POS_KEY_SIZE);
         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_scaleKeys = ByteBuffer.allocateDirect(numScaleKeys * 24);
+        m_scaleKeys = ByteBuffer.allocateDirect(numScaleKeys * SCALE_KEY_SIZE);
         m_scaleKeys.order(ByteOrder.nativeOrder());
     }
     
@@ -141,7 +140,7 @@ public final class AiNodeAnim {
      * Returns the buffer with position keys of this animation channel.<p>
      * 
      * 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>
      *
      * 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>
      * 
      * 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>
      * 
      * 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>
      * 
@@ -249,8 +291,24 @@ public final class Jassimp {
         /* 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 {
         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"""
 
 import sys, os, re
+from collections import OrderedDict
 
 re_match_entity = re.compile(r"""
 ENTITY\s+(\w+)\s*                                    # 'ENTITY foo'
@@ -68,8 +69,8 @@ re_match_field = re.compile(r"""
 
 class Schema:
     def __init__(self):
-        self.entities = {}
-        self.types = {}
+        self.entities = OrderedDict()
+        self.types = OrderedDict()
 
 class Entity:
     def __init__(self,name,parent,members):

+ 5 - 4
scripts/IFCImporter/entitylist.txt

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

+ 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


Fichier diff supprimé car celui-ci est trop grand
+ 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?
 ---------------------------------------------------------------------------------
-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?
 ---------------------------------------------------------------------------------
- - 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?
 ---------------------------------------------------------------------------------
 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
-<<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
-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. 
 Generally, almost all significant regressions will be detected while the
 number of false positives is relatively low.
 
 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)
 ---------------------------------------------------------------------------------
 As mentioned above, floating-point inaccuracies between differently optimized
 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,
          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
          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.
 
 -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
     for tp in settings.model_directories:
         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("Updated {0} entries".format(num))
@@ -172,43 +173,44 @@ def gen_db(ext_list,outfile):
 
 # -------------------------------------------------------------------------------
 if __name__ == "__main__":
-    assimp_bin_path = sys.argv[1] if len(sys.argv) > 1 else 'assimp'
-
     def clean(f):
         f = f.strip("* \'")
         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)
         sys.exit(0)
 
+    assimp_bin_path = sys.argv[1]    
     ext_list, preview, nozip = None, False, False
-    for m in sys.argv[1:]:
+    for m in sys.argv[2:]:
         if m[:10]=="--exclude=":
             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=":
             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":
             preview = True
         elif m=="-n" or m == "--nozip":
             nozip = True
+        else:
+            print("Unrecognized parameter: " + m)
+            sys.exit(-1)
             
     outfile = open(os.path.join("..", "results", "gen_regression_db_output.txt"), "w")
     if ext_list is None:
         (ext_list, err) = subprocess.Popen([assimp_bin_path, "listext"],
             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
     ext_list = list(filter(lambda f: not f in settings.exclude_extensions,
         map(clean, ext_list)))
-
-    if preview:
-        print(','.join(ext_list))
+    print('File extensions processed: ' + ', '.join(ext_list))
+    if preview:       
         sys.exit(1)
 
     extract_zip()    

+ 22 - 18
test/regression/run.py

@@ -65,7 +65,7 @@ import utils
 # -------------------------------------------------------------------------------
 EXPECTED_FAILURE_NOT_MET, DATABASE_LENGTH_MISMATCH, \
 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", {
         EXPECTED_FAILURE_NOT_MET:
@@ -88,7 +88,10 @@ messages = collections.defaultdict(lambda: "<unknown", {
 
         COMPARE_SUCCESS:
 """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"
@@ -167,11 +170,11 @@ def process_dir(d, outfile_results, zipin, result):
     print("Processing directory " + d)
     for f in sorted(os.listdir(d)):
         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)
             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)
             continue
 
@@ -190,32 +193,30 @@ def process_dir(d, outfile_results, zipin, result):
                     "regression database? Use gen_db.zip to re-generate.")
                 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) 
             
             outfile_actual = prepare_output_dir(fullpath, filehash, "ACTUAL")
             outfile_expect = prepare_output_dir(fullpath, filehash, "EXPECT")
             outfile_results.write("assimp dump    "+"-"*80+"\n")
             outfile_results.flush()
-
             command = [assimp_bin_path,
                 "dump",
                 fullpath, outfile_actual, "-b", "-s", "-l" ] +\
                 pppreset.split()
-
             r = subprocess.call(command, **shellparams)
-            print(r)
+            outfile_results.flush()
 
             if r and not failure:
                 result.fail(fullpath, outfile_expect, pppreset, IMPORT_FAILURE, r)
+                outfile_results.write("Failed to import\n")
                 continue
             elif failure and not r:
                 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
             
             with open(outfile_expect, "wb") as s:
@@ -227,21 +228,24 @@ def process_dir(d, outfile_results, zipin, result):
             except IOError:
                 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):
                 result.fail(fullpath, outfile_expect, pppreset, DATABASE_LENGTH_MISMATCH,
                         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.flush()
-
             command = [ assimp_bin_path, 'cmpdump', outfile_actual, outfile_expect ]
             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 
             
-            result.ok(fullpath, pppreset, COMPARE_SUCCESS, 
-                len(input_expected))     
+            result.ok(fullpath, pppreset, COMPARE_SUCCESS, len(input_expected))     
 
 # -------------------------------------------------------------------------------
 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
 # -------------------------------------------------------------------------------
 exclude_extensions = [
-    ".lws", ".assbin", ".assxml", ".txt", ".md",
+    ".assbin", ".assxml", ".txt", ".md",
     ".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
     and platforms, so we implement the hashing manually.
     """
-
+    file = file.lower()
     file = file.replace('\\','/')+":"+pp
     # SDBM hash
     res = 0
     for t in file:
         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

+ 1 - 1
tools/assimp_cmd/CMakeLists.txt

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

+ 37 - 14
tools/assimp_cmd/CompareDump.cpp

@@ -140,15 +140,16 @@ public:
 		if(it != history.back().second.end()) {
 			++history.back().second[s];
 		}
-		else history.back().second[s] = 1;
+		else history.back().second[s] = 0;
 
 		history.push_back(HistoryEntry(s,PerChunkCounter()));
-
+		debug_trace.push_back("PUSH " + s);
 	}
 
 	/* leave current scope */
 	void pop_elem() {
 		ai_assert(history.size());
+		debug_trace.push_back("POP "+ history.back().first);
 		history.pop_back();
 	}
 
@@ -249,30 +250,50 @@ private:
 		const char* last = history.back().first.c_str();
 		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();
 		}
 
+		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();
 	}
 
 
-	/* read from both streams simult.*/
+	/* read from both streams at the same time */
 	template <typename T> void read(T& filla,T& fille) {
 		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)) {
-			throw compare_fails_exception("Unexpected EOF reading EXPECT");
+			EOFExpect();
 		}
 	}
 
-
 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;
 
 	typedef std::map<std::string,unsigned int> PerChunkCounter;
@@ -281,6 +302,8 @@ private:
 	typedef std::deque<HistoryEntry> ChunkHistory;
 	ChunkHistory history;
 
+	std::vector<std::string> debug_trace;
+
 	typedef std::stack<std::pair<uint32_t,uint32_t> > LengthStack;
 	LengthStack lengths;
 
@@ -296,10 +319,10 @@ template <> void comparer_context :: read<aiString>(aiString& filla,aiString& fi
 	read(lena,lene);
 
 	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)) {
-		throw compare_fails_exception("Unexpected EOF reading ACTUAL");
+		EOFExpect();
 	}
 
 	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;
 
 		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) {
@@ -510,7 +533,7 @@ private:
 		if (current.first != actual.first) {
 			std::stringstream ss;
 			ctx.failure((ss
-				<<"Chunk lenghts do not match. EXPECT: "
+				<<"Chunk lengths do not match. EXPECT: "
 				<<current.second
 				<<" ACTUAL: " 
 				<< actual.second,
@@ -729,7 +752,7 @@ void CompareOnTheFlyLight(comparer_context& comp)	{
 	const aiLightSourceType type = static_cast<aiLightSourceType>( 
 		comp.cmp<uint32_t>("mType"));
 
-	if(type==aiLightSource_DIRECTIONAL) {
+	if(type!=aiLightSource_DIRECTIONAL) {
 		comp.cmp<float>("mAttenuationConstant");
 		comp.cmp<float>("mAttenuationLinear");
 		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

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff