Merge remote-tracking branch 'origin'

Conflicts:
	code/C4DImporter.cpp
	code/OgreImporter.h
pull/536/head
abma 2015-04-16 01:03:00 +02:00
commit 8c45a4dc3b
95 changed files with 32460 additions and 9658 deletions

6
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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);

View File

@ -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 );

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

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

View File

@ -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.

View File

@ -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)

View File

@ -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");
}

View File

@ -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;

View File

@ -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;
};

View File

@ -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

View File

@ -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;

View File

@ -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

View File

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

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

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

View File

@ -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) {
for(size_t n = 0; n < 2; ++n) {
size_t sides_with_v_openings = 0;
if( has_area ) {
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();

View File

@ -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()]();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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;
};
// ------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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;
}
}
// ------------------------------------------------------------------------------------------------

View File

@ -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.

View File

@ -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)
{

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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}
)

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:
};
// ----------------------------------------------------------------------------------
inline const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing )
class ASSIMP_API ExportProperties
{
return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing);
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, const ExportProperties* pProperties)
{
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

View File

@ -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

View File

@ -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>
<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}" />
<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>
<path id="classpath">
</path>
<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>
<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>

View File

@ -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)

View File

@ -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)
{

View File

@ -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

View File

@ -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;
/**

View File

@ -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

View File

@ -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();
}
}

View File

@ -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):

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -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"}
}
}

View File

@ -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.
- 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).
- 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?
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
- 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 suite?
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).

Binary file not shown.

View File

@ -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()

View File

@ -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):

View File

@ -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"
]
# -------------------------------------------------------------------------------

View File

@ -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

View File

@ -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
)

View File

@ -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");

View File

@ -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

View File

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