Merge branch 'master' of github.com:assimp/assimp

pull/89/merge
Alexander Gessler 2013-09-04 21:52:17 +02:00
commit 45572e8079
105 changed files with 12927 additions and 11587 deletions

1
.gitignore vendored 100644
View File

@ -0,0 +1 @@
build

17
.travis.yml 100644
View File

@ -0,0 +1,17 @@
before_install:
- sudo apt-get install cmake
env:
- TRAVIS_NO_EXPORT=YES
- TRAVIS_NO_EXPORT=NO
language: cpp
compiler:
- gcc
- clang
script: cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT && make

View File

@ -2,10 +2,9 @@ cmake_minimum_required( VERSION 2.6 )
PROJECT( Assimp ) PROJECT( Assimp )
# Define here the needed parameters # Define here the needed parameters
set (ASSIMP_SV_REVISION 1264)
set (ASSIMP_VERSION_MAJOR 3) set (ASSIMP_VERSION_MAJOR 3)
set (ASSIMP_VERSION_MINOR 0) set (ASSIMP_VERSION_MINOR 0)
set (ASSIMP_VERSION_PATCH ${ASSIMP_SV_REVISION}) # subversion revision? set (ASSIMP_VERSION_PATCH 1) # subversion revision?
set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
set (ASSIMP_SOVERSION 3) set (ASSIMP_SOVERSION 3)
SET ( PROJECT_VERSION "${ASSIMP_VERSION}" ) SET ( PROJECT_VERSION "${ASSIMP_VERSION}" )
@ -14,19 +13,25 @@ set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used f
option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF) option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules")
set(LIBASSIMP_COMPONENT libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}-r${ASSIMP_SV_REVISION}) set(LIBASSIMP_COMPONENT libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
set(LIBASSIMP-DEV_COMPONENT libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}-r${ASSIMP_SV_REVISION}-dev) set(LIBASSIMP-DEV_COMPONENT libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev)
set(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev) set(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
set(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it.... add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it....
## hide all not-exported symbols ## hide all not-exported symbols
add_definitions( -fvisibility=hidden -Wall ) add_definitions( -fvisibility=hidden -Wall )
elseif(MSVC)
# enable multi-core compilation with MSVC
add_definitions(/MP)
endif() endif()
INCLUDE (FindPkgConfig) INCLUDE (FindPkgConfig)
INCLUDE_DIRECTORIES( include ) INCLUDE_DIRECTORIES( include )
INCLUDE (PrecompiledHeader)
# If this is an in-source build (CMAKE_SOURCE_DIR == CMAKE_BINARY_DIR), # If this is an in-source build (CMAKE_SOURCE_DIR == CMAKE_BINARY_DIR),
# write the library/executable files to the respective directories in the # write the library/executable files to the respective directories in the
# source tree. During an out-of-source build, however, do not litter this # source tree. During an out-of-source build, however, do not litter this
@ -76,7 +81,7 @@ IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
MESSAGE( STATUS "Building a non-boost version of Assimp." ) MESSAGE( STATUS "Building a non-boost version of Assimp." )
ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND ) ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND )
SET( Boost_DETAILED_FAILURE_MSG ON ) SET( Boost_DETAILED_FAILURE_MSG ON )
SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0") SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0")
FIND_PACKAGE( Boost ) FIND_PACKAGE( Boost )
IF ( NOT Boost_FOUND ) IF ( NOT Boost_FOUND )
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR

View File

@ -0,0 +1,14 @@
===============================================
The Asset-Importer-Library Coding conventions
===============================================
If you want to participate to the Asset-Importer_Library please have a look
onto these coding conventions and try to follow them. They are more or less
some kind of guide line to help others coming into the code and help all
the Asset-Importer-Library users.
Tab width
===========
The tab width shall be 4 spaces.

View File

@ -1,2 +0,0 @@
[InternetShortcut]
URL=http://sourceforge.net/projects/assimp/

View File

@ -1,28 +1,11 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
======== ========
Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a single, in-memory format__. It supports more than 30 file formats. It also supports exporting files to a few selected file formats.
Table of contents Its abbreviated name under which it is commonly known is __assimp__.
1. Overview
1.1 Supported file formats
1.2 File structure
2. Build the library
3. Where to get help
4. License
### 1. Overview ###
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 30 file formats. It also supports exporting files to a few selected file formats.
Its short name is _assimp_, which is an unintended joke (the abbreviation is derived from _Asset Importer_).
__Note__: this `README` refers to the file structure used by release packages, which differs in some points from the development trunk.
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)
#### 1.1 Supported file formats #### #### 1.1 Supported file formats ####
@ -63,6 +46,10 @@ The library provides importers for a lot of file formats, including:
- Ogre XML - Ogre XML
- Q3D - Q3D
Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
- C4D (https://github.com/acgessler/assimp-cinema4d)
Exporters include: Exporters include:
- DAE (Collada) - DAE (Collada)
@ -129,5 +116,3 @@ The license of the Asset Import Library is based on the modified, __3-clause BSD
Note that, unlike LGPLed code, you may link statically to Assimp. Note that, unlike LGPLed code, you may link statically to Assimp.
For the formal details, see the `LICENSE` file. For the formal details, see the `LICENSE` file.
------------------------------

View File

@ -1,2 +0,0 @@
[InternetShortcut]
URL=http://assimp.sourceforge.net

View File

@ -1,13 +1,13 @@
set( ASSIMP_PACKAGE_VERSION "@ASSIMP_VERSION@" ) set( PACKAGE_VERSION "@ASSIMP_VERSION@" )
if( "${ASSIMP_PACKAGE_FIND_VERSION}" VERSION_EQUAL "@ASSIMP_VERSION@") if( "${PACKAGE_FIND_VERSION}" VERSION_EQUAL "@ASSIMP_VERSION@")
set(ASSIMP_PACKAGE_VERSION_EXACT 1) set(PACKAGE_VERSION_EXACT 1)
endif() endif()
if( "${ASSIMP_PACKAGE_FIND_VERSION_MAJOR}.${ASSIMP_PACKAGE_FIND_VERSION_MINOR}" EQUAL "@ASSIMP_SOVERSION@" ) if( "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@ASSIMP_SOVERSION@" )
set(ASSIMP_PACKAGE_VERSION_COMPATIBLE 1) set(PACKAGE_VERSION_COMPATIBLE 1)
elseif( "${ASSIMP_PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@ASSIMP_VERSION_MAJOR@" ) elseif( "${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@ASSIMP_VERSION_MAJOR@" )
# for now backward compatible if minor version is less # for now backward compatible if minor version is less
if( ${ASSIMP_PACKAGE_FIND_VERSION_MINOR} LESS @ASSIMP_VERSION_MINOR@ ) if( ${PACKAGE_FIND_VERSION_MINOR} LESS @ASSIMP_VERSION_MINOR@ )
set(ASSIMP_PACKAGE_VERSION_COMPATIBLE 1) set(PACKAGE_VERSION_COMPATIBLE 1)
endif() endif()
endif() endif()
set( ASSIMP_STATIC_LIB "@ASSIMP_BUILD_STATIC_LIB@") set( ASSIMP_STATIC_LIB "@ASSIMP_BUILD_STATIC_LIB@")

View File

@ -37,8 +37,8 @@ if( WIN32 )
set( ASSIMP_CXX_FLAGS " -DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB") set( ASSIMP_CXX_FLAGS " -DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB")
endif() endif()
set( ASSIMP_LINK_FLAGS "" ) set( ASSIMP_LINK_FLAGS "" )
set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@LIB_INSTALL_DIR@") set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@")
set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@INCLUDE_INSTALL_DIR@") set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@")
set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX}) set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX})
# the boost version assimp was compiled with # the boost version assimp was compiled with

View File

@ -0,0 +1,25 @@
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
IF(MSVC)
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
SET(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${PrecompiledBasename}.pch")
SET(Sources ${${SourcesVar}})
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_OUTPUTS "${PrecompiledBinary}")
# Do not consider .c files
foreach(fname ${Sources})
GET_FILENAME_COMPONENT(fext ${fname} EXT)
if(fext STREQUAL ".cpp")
SET_SOURCE_FILES_PROPERTIES(${fname}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledBinary}\" /FI\"${PrecompiledBinary}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
endif(fext STREQUAL ".cpp")
endforeach(fname)
ENDIF(MSVC)
# Add precompiled header to SourcesVar
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)

View File

@ -707,7 +707,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
if (0 == mRootNode->mChildren.size()) if (0 == mRootNode->mChildren.size())
{ {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// It seems the file is so fucked up that it has not even a hierarchy. // It seems the file is so messed up that it has not even a hierarchy.
// generate a flat hiearachy which looks like this: // generate a flat hiearachy which looks like this:
// //
// ROOT_NODE // ROOT_NODE

View File

@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/assimp/types.h" #include "../include/assimp/types.h"
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
struct aiNode; struct aiNode;
#include "3DSHelper.h" #include "3DSHelper.h"
@ -271,6 +273,8 @@ protected:
bool bIsPrj; bool bIsPrj;
}; };
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
} // end of namespace Assimp } // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_INC #endif // AI_3DSIMPORTER_H_INC

View File

@ -1567,8 +1567,8 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
unsigned int iIndex = strtoul10(filePtr,&filePtr); unsigned int iIndex = strtoul10(filePtr,&filePtr);
if (iIndex >= iNumBones) if (iIndex >= iNumBones)
{ {
continue;
LogWarning("Bone index is out of bounds"); LogWarning("Bone index is out of bounds");
continue;
} }
if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME")) if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
SkipToNextToken(); SkipToNextToken();

View File

@ -1,3 +1,4 @@
/* /*
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -624,7 +625,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
) )
{ {
typedef std::pair<const int,size_t> MyPair; typedef std::pair<const int,size_t> MyPair;
if (!mesh->totface || !mesh->totvert) { if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
return; return;
} }
@ -637,12 +638,24 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ThrowException("Number of vertices is larger than the corresponding array"); ThrowException("Number of vertices is larger than the corresponding array");
} }
if (static_cast<size_t> ( mesh->totloop ) > mesh->mloop.size()) {
ThrowException("Number of vertices is larger than the corresponding array");
}
// collect per-submesh numbers // collect per-submesh numbers
std::map<int,size_t> per_mat; std::map<int,size_t> per_mat;
std::map<int,size_t> per_mat_verts;
for (int i = 0; i < mesh->totface; ++i) { for (int i = 0; i < mesh->totface; ++i) {
const MFace& mf = mesh->mface[i]; const MFace& mf = mesh->mface[i];
per_mat[ mf.mat_nr ]++; per_mat[ mf.mat_nr ]++;
per_mat_verts[ mf.mat_nr ] += mf.v4?4:3;
}
for (int i = 0; i < mesh->totpoly; ++i) {
const MPoly& mp = mesh->mpoly[i];
per_mat[ mp.mat_nr ]++;
per_mat_verts[ mp.mat_nr ] += mp.totloop;
} }
// ... and allocate the corresponding meshes // ... and allocate the corresponding meshes
@ -656,8 +669,8 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
temp->push_back(new aiMesh()); temp->push_back(new aiMesh());
aiMesh* out = temp->back(); aiMesh* out = temp->back();
out->mVertices = new aiVector3D[it.second*4]; out->mVertices = new aiVector3D[per_mat_verts[it.first]];
out->mNormals = new aiVector3D[it.second*4]; out->mNormals = new aiVector3D[per_mat_verts[it.first]];
//out->mNumFaces = 0 //out->mNumFaces = 0
//out->mNumVertices = 0 //out->mNumVertices = 0
@ -780,8 +793,56 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
// } // }
} }
for (int i = 0; i < mesh->totpoly; ++i) {
const MPoly& mf = mesh->mpoly[i];
aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
aiFace& f = out->mFaces[out->mNumFaces++];
f.mIndices = new unsigned int[ f.mNumIndices = mf.totloop ];
aiVector3D* vo = out->mVertices + out->mNumVertices;
aiVector3D* vn = out->mNormals + out->mNumVertices;
// XXX we can't fold this easily, because we are restricted
// to the member names from the BLEND file (v1,v2,v3,v4)
// which are assigned by the genblenddna.py script and
// cannot be changed without breaking the entire
// import process.
for (int j = 0;j < mf.totloop; ++j)
{
const MLoop& loop = mesh->mloop[mf.loopstart + j];
if (loop.v >= mesh->totvert) {
ThrowException("Vertex index out of range");
}
const MVert& v = mesh->mvert[loop.v];
vo->x = v.co[0];
vo->y = v.co[1];
vo->z = v.co[2];
vn->x = v.no[0];
vn->y = v.no[1];
vn->z = v.no[2];
f.mIndices[j] = out->mNumVertices++;
++vo;
++vn;
}
if (mf.totloop == 3)
{
out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
}
else
{
out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
}
}
// collect texture coordinates, they're stored in a separate per-face buffer // collect texture coordinates, they're stored in a separate per-face buffer
if (mesh->mtface) { if (mesh->mtface || mesh->mloopuv) {
if (mesh->totface > static_cast<int> ( mesh->mtface.size())) { if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)"); ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
} }
@ -804,6 +865,20 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
vo->y = v->uv[i][1]; vo->y = v->uv[i][1];
} }
} }
for (int i = 0; i < mesh->totpoly; ++i) {
const MPoly& v = mesh->mpoly[i];
aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
const aiFace& f = out->mFaces[out->mNumFaces++];
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
vo->x = uv.uv[0];
vo->y = uv.uv[1];
}
}
} }
// collect texture coordinates, old-style (marked as deprecated in current blender sources) // collect texture coordinates, old-style (marked as deprecated in current blender sources)
@ -833,7 +908,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
} }
// collect vertex colors, stored separately as well // collect vertex colors, stored separately as well
if (mesh->mcol) { if (mesh->mcol || mesh->mloopcol) {
if (mesh->totface > static_cast<int> ( (mesh->mcol.size()/4)) ) { if (mesh->totface > static_cast<int> ( (mesh->mcol.size()/4)) ) {
ThrowException("Number of faces is larger than the corresponding color face array"); ThrowException("Number of faces is larger than the corresponding color face array");
} }
@ -860,6 +935,23 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
} }
for (unsigned int n = f.mNumIndices; n < 4; ++n); for (unsigned int n = f.mNumIndices; n < 4; ++n);
} }
for (int i = 0; i < mesh->totpoly; ++i) {
const MPoly& v = mesh->mpoly[i];
aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
const aiFace& f = out->mFaces[out->mNumFaces++];
aiColor4D* vo = &out->mColors[0][out->mNumVertices];
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
const MLoopCol& col = mesh->mloopcol[v.loopstart + j];
vo->r = col.r;
vo->g = col.g;
vo->b = col.b;
vo->a = col.a;
}
}
} }
return; return;

View File

@ -305,6 +305,27 @@ template <> void Structure :: Convert<Material> (
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//--------------------------------------------------------------------------------
template <> void Structure :: Convert<MTexPoly> (
MTexPoly& dest,
const FileDatabase& db
) const
{
{
boost::shared_ptr<Image> tpage;
ReadFieldPtr<ErrorPolicy_Igno>(tpage,"*tpage",db);
dest.tpage = tpage.get();
}
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
ReadField<ErrorPolicy_Igno>(dest.transp,"transp",db);
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
db.reader->IncPtr(size);
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <> void Structure :: Convert<Mesh> ( template <> void Structure :: Convert<Mesh> (
Mesh& dest, Mesh& dest,
@ -316,6 +337,8 @@ template <> void Structure :: Convert<Mesh> (
ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db); ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db);
ReadField<ErrorPolicy_Fail>(dest.totedge,"totedge",db); ReadField<ErrorPolicy_Fail>(dest.totedge,"totedge",db);
ReadField<ErrorPolicy_Fail>(dest.totvert,"totvert",db); ReadField<ErrorPolicy_Fail>(dest.totvert,"totvert",db);
ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
ReadField<ErrorPolicy_Igno>(dest.totpoly,"totpoly",db);
ReadField<ErrorPolicy_Igno>(dest.subdiv,"subdiv",db); ReadField<ErrorPolicy_Igno>(dest.subdiv,"subdiv",db);
ReadField<ErrorPolicy_Igno>(dest.subdivr,"subdivr",db); ReadField<ErrorPolicy_Igno>(dest.subdivr,"subdivr",db);
ReadField<ErrorPolicy_Igno>(dest.subsurftype,"subsurftype",db); ReadField<ErrorPolicy_Igno>(dest.subsurftype,"subsurftype",db);
@ -325,6 +348,11 @@ template <> void Structure :: Convert<Mesh> (
ReadFieldPtr<ErrorPolicy_Igno>(dest.tface,"*tface",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.tface,"*tface",db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.mvert,"*mvert",db); ReadFieldPtr<ErrorPolicy_Fail>(dest.mvert,"*mvert",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.medge,"*medge",db); ReadFieldPtr<ErrorPolicy_Warn>(dest.medge,"*medge",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mloop,"*mloop",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopuv,"*mloopuv",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopcol,"*mloopcol",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mpoly,"*mpoly",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mtpoly,"*mtpoly",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.dvert,"*dvert",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.dvert,"*dvert",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db); ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
@ -357,6 +385,21 @@ template <> void Structure :: Convert<World> (
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//--------------------------------------------------------------------------------
template <> void Structure :: Convert<MLoopCol> (
MLoopCol& dest,
const FileDatabase& db
) const
{
ReadField<ErrorPolicy_Igno>(dest.r,"r",db);
ReadField<ErrorPolicy_Igno>(dest.g,"g",db);
ReadField<ErrorPolicy_Igno>(dest.b,"b",db);
ReadField<ErrorPolicy_Igno>(dest.a,"a",db);
db.reader->IncPtr(size);
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <> void Structure :: Convert<MVert> ( template <> void Structure :: Convert<MVert> (
MVert& dest, MVert& dest,
@ -389,6 +432,19 @@ template <> void Structure :: Convert<MEdge> (
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//--------------------------------------------------------------------------------
template <> void Structure :: Convert<MLoopUV> (
MLoopUV& dest,
const FileDatabase& db
) const
{
ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
db.reader->IncPtr(size);
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <> void Structure :: Convert<GroupObject> ( template <> void Structure :: Convert<GroupObject> (
GroupObject& dest, GroupObject& dest,
@ -416,6 +472,19 @@ template <> void Structure :: Convert<ListBase> (
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//--------------------------------------------------------------------------------
template <> void Structure :: Convert<MLoop> (
MLoop& dest,
const FileDatabase& db
) const
{
ReadField<ErrorPolicy_Igno>(dest.v,"v",db);
ReadField<ErrorPolicy_Igno>(dest.e,"e",db);
db.reader->IncPtr(size);
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <> void Structure :: Convert<ModifierData> ( template <> void Structure :: Convert<ModifierData> (
ModifierData& dest, ModifierData& dest,
@ -461,34 +530,16 @@ template <> void Structure :: Convert<MCol> (
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <> void Structure :: Convert<Image> ( template <> void Structure :: Convert<MPoly> (
Image& dest, MPoly& dest,
const FileDatabase& db const FileDatabase& db
) const ) const
{ {
ReadField<ErrorPolicy_Fail>(dest.id,"id",db); ReadField<ErrorPolicy_Igno>(dest.loopstart,"loopstart",db);
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db); ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
ReadField<ErrorPolicy_Igno>(dest.ok,"ok",db); ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
ReadField<ErrorPolicy_Igno>(dest.source,"source",db);
ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
ReadField<ErrorPolicy_Igno>(dest.pad1,"pad1",db);
ReadField<ErrorPolicy_Igno>(dest.lastframe,"lastframe",db);
ReadField<ErrorPolicy_Igno>(dest.tpageflag,"tpageflag",db);
ReadField<ErrorPolicy_Igno>(dest.totbind,"totbind",db);
ReadField<ErrorPolicy_Igno>(dest.xrep,"xrep",db);
ReadField<ErrorPolicy_Igno>(dest.yrep,"yrep",db);
ReadField<ErrorPolicy_Igno>(dest.twsta,"twsta",db);
ReadField<ErrorPolicy_Igno>(dest.twend,"twend",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.packedfile,"*packedfile",db);
ReadField<ErrorPolicy_Igno>(dest.lastupdate,"lastupdate",db);
ReadField<ErrorPolicy_Igno>(dest.lastused,"lastused",db);
ReadField<ErrorPolicy_Igno>(dest.animspeed,"animspeed",db);
ReadField<ErrorPolicy_Igno>(dest.gen_x,"gen_x",db);
ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
@ -568,6 +619,39 @@ template <> void Structure :: Convert<MirrorModifierData> (
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//--------------------------------------------------------------------------------
template <> void Structure :: Convert<Image> (
Image& dest,
const FileDatabase& db
) const
{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
ReadField<ErrorPolicy_Igno>(dest.ok,"ok",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
ReadField<ErrorPolicy_Igno>(dest.source,"source",db);
ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
ReadField<ErrorPolicy_Igno>(dest.pad1,"pad1",db);
ReadField<ErrorPolicy_Igno>(dest.lastframe,"lastframe",db);
ReadField<ErrorPolicy_Igno>(dest.tpageflag,"tpageflag",db);
ReadField<ErrorPolicy_Igno>(dest.totbind,"totbind",db);
ReadField<ErrorPolicy_Igno>(dest.xrep,"xrep",db);
ReadField<ErrorPolicy_Igno>(dest.yrep,"yrep",db);
ReadField<ErrorPolicy_Igno>(dest.twsta,"twsta",db);
ReadField<ErrorPolicy_Igno>(dest.twend,"twend",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.packedfile,"*packedfile",db);
ReadField<ErrorPolicy_Igno>(dest.lastupdate,"lastupdate",db);
ReadField<ErrorPolicy_Igno>(dest.lastused,"lastused",db);
ReadField<ErrorPolicy_Igno>(dest.animspeed,"animspeed",db);
ReadField<ErrorPolicy_Igno>(dest.gen_x,"gen_x",db);
ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
db.reader->IncPtr(size);
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
void DNA::RegisterConverters() { void DNA::RegisterConverters() {
@ -583,22 +667,27 @@ void DNA::RegisterConverters() {
converters["Base"] = DNA::FactoryPair( &Structure::Allocate<Base>, &Structure::Convert<Base> ); converters["Base"] = DNA::FactoryPair( &Structure::Allocate<Base>, &Structure::Convert<Base> );
converters["MTFace"] = DNA::FactoryPair( &Structure::Allocate<MTFace>, &Structure::Convert<MTFace> ); converters["MTFace"] = DNA::FactoryPair( &Structure::Allocate<MTFace>, &Structure::Convert<MTFace> );
converters["Material"] = DNA::FactoryPair( &Structure::Allocate<Material>, &Structure::Convert<Material> ); converters["Material"] = DNA::FactoryPair( &Structure::Allocate<Material>, &Structure::Convert<Material> );
converters["MTexPoly"] = DNA::FactoryPair( &Structure::Allocate<MTexPoly>, &Structure::Convert<MTexPoly> );
converters["Mesh"] = DNA::FactoryPair( &Structure::Allocate<Mesh>, &Structure::Convert<Mesh> ); converters["Mesh"] = DNA::FactoryPair( &Structure::Allocate<Mesh>, &Structure::Convert<Mesh> );
converters["MDeformVert"] = DNA::FactoryPair( &Structure::Allocate<MDeformVert>, &Structure::Convert<MDeformVert> ); converters["MDeformVert"] = DNA::FactoryPair( &Structure::Allocate<MDeformVert>, &Structure::Convert<MDeformVert> );
converters["World"] = DNA::FactoryPair( &Structure::Allocate<World>, &Structure::Convert<World> ); converters["World"] = DNA::FactoryPair( &Structure::Allocate<World>, &Structure::Convert<World> );
converters["MLoopCol"] = DNA::FactoryPair( &Structure::Allocate<MLoopCol>, &Structure::Convert<MLoopCol> );
converters["MVert"] = DNA::FactoryPair( &Structure::Allocate<MVert>, &Structure::Convert<MVert> ); converters["MVert"] = DNA::FactoryPair( &Structure::Allocate<MVert>, &Structure::Convert<MVert> );
converters["MEdge"] = DNA::FactoryPair( &Structure::Allocate<MEdge>, &Structure::Convert<MEdge> ); converters["MEdge"] = DNA::FactoryPair( &Structure::Allocate<MEdge>, &Structure::Convert<MEdge> );
converters["MLoopUV"] = DNA::FactoryPair( &Structure::Allocate<MLoopUV>, &Structure::Convert<MLoopUV> );
converters["GroupObject"] = DNA::FactoryPair( &Structure::Allocate<GroupObject>, &Structure::Convert<GroupObject> ); converters["GroupObject"] = DNA::FactoryPair( &Structure::Allocate<GroupObject>, &Structure::Convert<GroupObject> );
converters["ListBase"] = DNA::FactoryPair( &Structure::Allocate<ListBase>, &Structure::Convert<ListBase> ); converters["ListBase"] = DNA::FactoryPair( &Structure::Allocate<ListBase>, &Structure::Convert<ListBase> );
converters["MLoop"] = DNA::FactoryPair( &Structure::Allocate<MLoop>, &Structure::Convert<MLoop> );
converters["ModifierData"] = DNA::FactoryPair( &Structure::Allocate<ModifierData>, &Structure::Convert<ModifierData> ); converters["ModifierData"] = DNA::FactoryPair( &Structure::Allocate<ModifierData>, &Structure::Convert<ModifierData> );
converters["ID"] = DNA::FactoryPair( &Structure::Allocate<ID>, &Structure::Convert<ID> ); converters["ID"] = DNA::FactoryPair( &Structure::Allocate<ID>, &Structure::Convert<ID> );
converters["MCol"] = DNA::FactoryPair( &Structure::Allocate<MCol>, &Structure::Convert<MCol> ); converters["MCol"] = DNA::FactoryPair( &Structure::Allocate<MCol>, &Structure::Convert<MCol> );
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> ); converters["MPoly"] = DNA::FactoryPair( &Structure::Allocate<MPoly>, &Structure::Convert<MPoly> );
converters["Scene"] = DNA::FactoryPair( &Structure::Allocate<Scene>, &Structure::Convert<Scene> ); converters["Scene"] = DNA::FactoryPair( &Structure::Allocate<Scene>, &Structure::Convert<Scene> );
converters["Library"] = DNA::FactoryPair( &Structure::Allocate<Library>, &Structure::Convert<Library> ); converters["Library"] = DNA::FactoryPair( &Structure::Allocate<Library>, &Structure::Convert<Library> );
converters["Tex"] = DNA::FactoryPair( &Structure::Allocate<Tex>, &Structure::Convert<Tex> ); converters["Tex"] = DNA::FactoryPair( &Structure::Allocate<Tex>, &Structure::Convert<Tex> );
converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> ); converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> ); converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
} }

View File

@ -94,6 +94,7 @@ namespace Assimp {
struct Object; struct Object;
struct MTex; struct MTex;
struct Image;
#define AI_BLEND_MESH_MAX_VERTS 2000000000L #define AI_BLEND_MESH_MAX_VERTS 2000000000L
@ -156,6 +157,38 @@ struct MEdge : ElemBase {
short flag; short flag;
}; };
// -------------------------------------------------------------------------------
struct MLoop : ElemBase {
int v, e;
};
// -------------------------------------------------------------------------------
struct MLoopUV : ElemBase {
float uv[2];
int flag;
};
// -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase {
char r, g, b, a;
};
// -------------------------------------------------------------------------------
struct MPoly : ElemBase {
int loopstart;
int totloop;
short mat_nr;
char flag;
};
// -------------------------------------------------------------------------------
struct MTexPoly : ElemBase {
Image* tpage;
char flag, transp;
short mode, tile, pad;
};
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MCol : ElemBase { struct MCol : ElemBase {
char r,g,b,a FAIL; char r,g,b,a FAIL;
@ -235,6 +268,8 @@ struct Mesh : ElemBase {
int totface FAIL; int totface FAIL;
int totedge FAIL; int totedge FAIL;
int totvert FAIL; int totvert FAIL;
int totloop;
int totpoly;
short subdiv; short subdiv;
short subdivr; short subdivr;
@ -246,6 +281,11 @@ struct Mesh : ElemBase {
vector<TFace> tface; vector<TFace> tface;
vector<MVert> mvert FAIL; vector<MVert> mvert FAIL;
vector<MEdge> medge WARN; vector<MEdge> medge WARN;
vector<MLoop> mloop;
vector<MLoopUV> mloopuv;
vector<MLoopCol> mloopcol;
vector<MPoly> mpoly;
vector<MTexPoly> mtpoly;
vector<MDeformVert> dvert; vector<MDeformVert> dvert;
vector<MCol> mcol; vector<MCol> mcol;

View File

@ -120,6 +120,12 @@ template <> void Structure :: Convert<Material> (
) const ) const
; ;
template <> void Structure :: Convert<MTexPoly> (
MTexPoly& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Mesh> ( template <> void Structure :: Convert<Mesh> (
Mesh& dest, Mesh& dest,
const FileDatabase& db const FileDatabase& db
@ -138,6 +144,12 @@ template <> void Structure :: Convert<World> (
) const ) const
; ;
template <> void Structure :: Convert<MLoopCol> (
MLoopCol& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MVert> ( template <> void Structure :: Convert<MVert> (
MVert& dest, MVert& dest,
const FileDatabase& db const FileDatabase& db
@ -150,6 +162,12 @@ template <> void Structure :: Convert<MEdge> (
) const ) const
; ;
template <> void Structure :: Convert<MLoopUV> (
MLoopUV& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<GroupObject> ( template <> void Structure :: Convert<GroupObject> (
GroupObject& dest, GroupObject& dest,
const FileDatabase& db const FileDatabase& db
@ -162,6 +180,12 @@ template <> void Structure :: Convert<ListBase> (
) const ) const
; ;
template <> void Structure :: Convert<MLoop> (
MLoop& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<ModifierData> ( template <> void Structure :: Convert<ModifierData> (
ModifierData& dest, ModifierData& dest,
const FileDatabase& db const FileDatabase& db
@ -180,8 +204,8 @@ template <> void Structure :: Convert<MCol> (
) const ) const
; ;
template <> void Structure :: Convert<Image> ( template <> void Structure :: Convert<MPoly> (
Image& dest, MPoly& dest,
const FileDatabase& db const FileDatabase& db
) const ) const
; ;
@ -216,6 +240,12 @@ template <> void Structure :: Convert<MirrorModifierData> (
) const ) const
; ;
template <> void Structure :: Convert<Image> (
Image& dest,
const FileDatabase& db
) const
;
} }
} }

View File

@ -88,9 +88,9 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Read(void* pvBuffer, virtual size_t Read( void *,
size_t pSize, size_t,
size_t pCount) size_t )
{ {
return 0; return 0;
} }

View File

@ -3,6 +3,8 @@
#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST #ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST
#define __AI_BOOST_WORKAROUND_LEXICAL_CAST #define __AI_BOOST_WORKAROUND_LEXICAL_CAST
#include <sstream>
namespace boost namespace boost
{ {

View File

@ -175,13 +175,13 @@ namespace boost {
// Get a specific tuple element // Get a specific tuple element
template <unsigned N> template <unsigned N>
typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () { typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () {
return m.get<N>(); return m.template get<N>();
} }
// ... and the const version // ... and the const version
template <unsigned N> template <unsigned N>
const typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const { const typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const {
return m.get<N>(); return m.template get<N>();
} }
@ -208,14 +208,14 @@ namespace boost {
template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4> template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
inline typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get ( inline typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
tuple<T0,T1,T2,T3,T4>& m) { tuple<T0,T1,T2,T3,T4>& m) {
return m.get<N>(); return m.template get<N>();
} }
// ... and the const version // ... and the const version
template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4> template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
inline const typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get ( inline const typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
const tuple<T0,T1,T2,T3,T4>& m) { const tuple<T0,T1,T2,T3,T4>& m) {
return m.get<N>(); return m.template get<N>();
} }
// Constructs a tuple with 5 elements // Constructs a tuple with 5 elements
@ -224,11 +224,11 @@ namespace boost {
const T1& t1,const T2& t2,const T3& t3,const T4& t4) { const T1& t1,const T2& t2,const T3& t3,const T4& t4) {
tuple <T0,T1,T2,T3,T4> t; tuple <T0,T1,T2,T3,T4> t;
t.get<0>() = t0; t.template get<0>() = t0;
t.get<1>() = t1; t.template get<1>() = t1;
t.get<2>() = t2; t.template get<2>() = t2;
t.get<3>() = t3; t.template get<3>() = t3;
t.get<4>() = t4; t.template get<4>() = t4;
return t; return t;
} }
@ -237,10 +237,10 @@ namespace boost {
inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0, inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0,
const T1& t1,const T2& t2,const T3& t3) { const T1& t1,const T2& t2,const T3& t3) {
tuple <T0,T1,T2,T3> t; tuple <T0,T1,T2,T3> t;
t.get<0>() = t0; t.template get<0>() = t0;
t.get<1>() = t1; t.template get<1>() = t1;
t.get<2>() = t2; t.template get<2>() = t2;
t.get<3>() = t3; t.template get<3>() = t3;
return t; return t;
} }
@ -249,31 +249,31 @@ namespace boost {
inline tuple <T0,T1,T2> make_tuple (const T0& t0, inline tuple <T0,T1,T2> make_tuple (const T0& t0,
const T1& t1,const T2& t2) { const T1& t1,const T2& t2) {
tuple <T0,T1,T2> t; tuple <T0,T1,T2> t;
t.get<0>() = t0; t.template get<0>() = t0;
t.get<1>() = t1; t.template get<1>() = t1;
t.get<2>() = t2; t.template get<2>() = t2;
return t; return t;
} }
// Constructs a tuple with 2 elements (fucking idiot, use std::pair instead!) // Constructs a tuple with 2 elements
template <typename T0,typename T1> template <typename T0,typename T1>
inline tuple <T0,T1> make_tuple (const T0& t0, inline tuple <T0,T1> make_tuple (const T0& t0,
const T1& t1) { const T1& t1) {
tuple <T0,T1> t; tuple <T0,T1> t;
t.get<0>() = t0; t.template get<0>() = t0;
t.get<1>() = t1; t.template get<1>() = t1;
return t; return t;
} }
// Constructs a tuple with 1 elements (no comment ...) // Constructs a tuple with 1 elements (well ...)
template <typename T0> template <typename T0>
inline tuple <T0> make_tuple (const T0& t0) { inline tuple <T0> make_tuple (const T0& t0) {
tuple <T0> t; tuple <T0> t;
t.get<0>() = t0; t.template get<0>() = t0;
return t; return t;
} }
// Constructs a tuple with 0 elements (ehm? Try http://www.promillerechner.net) // Constructs a tuple with 0 elements (well ...)
inline tuple <> make_tuple () { inline tuple <> make_tuple () {
tuple <> t; tuple <> t;
return t; return t;

View File

@ -34,6 +34,7 @@ SET( PUBLIC_HEADERS
${HEADER_PATH}/quaternion.h ${HEADER_PATH}/quaternion.h
${HEADER_PATH}/quaternion.inl ${HEADER_PATH}/quaternion.inl
${HEADER_PATH}/scene.h ${HEADER_PATH}/scene.h
${HEADER_PATH}/metadata.h
${HEADER_PATH}/texture.h ${HEADER_PATH}/texture.h
${HEADER_PATH}/types.h ${HEADER_PATH}/types.h
${HEADER_PATH}/vector2.h ${HEADER_PATH}/vector2.h
@ -57,8 +58,6 @@ SET( PUBLIC_HEADERS
SET( Core_SRCS SET( Core_SRCS
Assimp.cpp Assimp.cpp
AssimpPCH.cpp
AssimpPCH.h
) )
SET( Boost_SRCS SET( Boost_SRCS
@ -237,11 +236,7 @@ SET( LWS_SRCS
) )
SOURCE_GROUP( LWS FILES ${LWS_SRCS}) SOURCE_GROUP( LWS FILES ${LWS_SRCS})
SET ( M3_SRCS
M3Importer.cpp
M3Importer.h
)
SOURCE_GROUP( M3 FILES ${M3_SRCS} )
SET( MD2_SRCS SET( MD2_SRCS
MD2FileData.h MD2FileData.h
@ -619,7 +614,7 @@ else (UNZIP_FOUND)
SET (unzip_compile_SRCS ${unzip_SRCS}) SET (unzip_compile_SRCS ${unzip_SRCS})
endif (UNZIP_FOUND) endif (UNZIP_FOUND)
SET( assim_src SET( assimp_src
# Assimp Files # Assimp Files
${Core_SRCS} ${Core_SRCS}
${Common_SRCS} ${Common_SRCS}
@ -640,7 +635,6 @@ SET( assim_src
${Irr_SRCS} ${Irr_SRCS}
${LWO_SRCS} ${LWO_SRCS}
${LWS_SRCS} ${LWS_SRCS}
${M3_SRCS}
${MD2_SRCS} ${MD2_SRCS}
${MD3_SRCS} ${MD3_SRCS}
${MD5_SRCS} ${MD5_SRCS}
@ -680,13 +674,16 @@ SET( assim_src
${PUBLIC_HEADERS} ${PUBLIC_HEADERS}
${COMPILER_HEADERS} ${COMPILER_HEADERS}
) )
ADD_MSVC_PRECOMPILED_HEADER("AssimpPCH.h" "AssimpPCH.cpp" assimp_src)
IF ( ASSIMP_BUILD_STATIC_LIB ) IF ( ASSIMP_BUILD_STATIC_LIB )
ADD_LIBRARY( assimp STATIC ADD_LIBRARY( assimp STATIC
${assim_src} ${assimp_src}
) )
ELSE ( ASSIMP_BUILD_STATIC_LIB ) ELSE ( ASSIMP_BUILD_STATIC_LIB )
ADD_LIBRARY( assimp SHARED ADD_LIBRARY( assimp SHARED
${assim_src} ${assimp_src}
) )
ENDIF ( ASSIMP_BUILD_STATIC_LIB ) ENDIF ( ASSIMP_BUILD_STATIC_LIB )
@ -696,6 +693,7 @@ TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES})
SET_TARGET_PROPERTIES( assimp PROPERTIES SET_TARGET_PROPERTIES( assimp PROPERTIES
VERSION ${ASSIMP_VERSION} VERSION ${ASSIMP_VERSION}
SOVERSION ${ASSIMP_SOVERSION} # use full version SOVERSION ${ASSIMP_SOVERSION} # use full version
OUTPUT_NAME assimp${ASSIMP_LIBRARY_SUFFIX}
) )
# Build against external unzip, or add ../contrib/unzip so # Build against external unzip, or add ../contrib/unzip so
# assimp can #include "unzip.h" # assimp can #include "unzip.h"

View File

@ -1045,9 +1045,9 @@ void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const
v.y = reader.GetF4(); v.y = reader.GetF4();
} }
const size_t numfuck = reader.GetI4(); const size_t numf = reader.GetI4();
msh.faces.reserve(numfuck); msh.faces.reserve(numf);
for(size_t i = 0; i < numfuck; ++i) { for(size_t i = 0; i < numf; ++i) {
// XXX backface culling flag is 0x10 in flags // XXX backface culling flag is 0x10 in flags
// hole? // hole?

View File

@ -58,6 +58,9 @@ void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pS
// we're still here - export successfully completed. Write result to the given IOSYstem // we're still here - export successfully completed. Write result to the given IOSYstem
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .dae file: " + std::string(pFile));
}
// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy. // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1); outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
@ -99,7 +102,7 @@ void ColladaExporter::WriteFile()
WriteSceneLibrary(); WriteSceneLibrary();
// useless Collada bullshit at the end, just in case we haven't had enough indirections, yet. // useless Collada fu at the end, just in case we haven't had enough indirections, yet.
mOutput << startstr << "<scene>" << endstr; mOutput << startstr << "<scene>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<instance_visual_scene url=\"#myScene\" />" << endstr; mOutput << startstr << "<instance_visual_scene url=\"#myScene\" />" << endstr;
@ -495,7 +498,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
mOutput << "</float_array>" << endstr; mOutput << "</float_array>" << endstr;
PopTag(); PopTag();
// the usual Collada bullshit. Let's bloat it even more! // the usual Collada fun. Let's bloat it even more!
mOutput << startstr << "<technique_common>" << endstr; mOutput << startstr << "<technique_common>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<accessor count=\"" << pElementCount << "\" offset=\"0\" source=\"#" << arrayId << "\" stride=\"" << floatsPerElement << "\">" << endstr; mOutput << startstr << "<accessor count=\"" << pElementCount << "\" offset=\"0\" source=\"#" << arrayId << "\" stride=\"" << floatsPerElement << "\">" << endstr;

View File

@ -119,6 +119,7 @@ struct Camera
}; };
#define aiLightSource_AMBIENT 0xdeaddead #define aiLightSource_AMBIENT 0xdeaddead
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
/** A collada light source. */ /** A collada light source. */
struct Light struct Light
@ -129,8 +130,8 @@ struct Light
, mAttQuadratic (0.f) , mAttQuadratic (0.f)
, mFalloffAngle (180.f) , mFalloffAngle (180.f)
, mFalloffExponent (0.f) , mFalloffExponent (0.f)
, mPenumbraAngle (10e10f) , mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
, mOuterAngle (10e10f) , mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
, mIntensity (1.f) , mIntensity (1.f)
{} {}
@ -321,6 +322,8 @@ struct Mesh
mNumUVComponents[i] = 2; mNumUVComponents[i] = 2;
} }
std::string mName;
// just to check if there's some sophisticated addressing involved... // just to check if there's some sophisticated addressing involved...
// which we don't support, and therefore should warn about. // which we don't support, and therefore should warn about.
std::string mVertexID; std::string mVertexID;

View File

@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ColladaLoader::ColladaLoader() ColladaLoader::ColladaLoader()
: noSkeletonMesh() : noSkeletonMesh(), ignoreUpDirection(false)
{} {}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -108,6 +108,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
void ColladaLoader::SetupProperties(const Importer* pImp) void ColladaLoader::SetupProperties(const Importer* pImp)
{ {
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
} }
@ -155,20 +156,26 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// ... then fill the materials with the now adjusted settings // ... then fill the materials with the now adjusted settings
FillMaterials(parser, pScene); FillMaterials(parser, pScene);
// Convert to Y_UP, if different orientation // Apply unitsize scale calculation
if( parser.mUpDirection == ColladaParser::UP_X) pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
pScene->mRootNode->mTransformation *= aiMatrix4x4( 0, parser.mUnitSize, 0, 0,
0, -1, 0, 0, 0, 0, parser.mUnitSize, 0,
1, 0, 0, 0, 0, 0, 0, 1);
0, 0, 1, 0, if( !ignoreUpDirection ) {
0, 0, 0, 1); // Convert to Y_UP, if different orientation
else if( parser.mUpDirection == ColladaParser::UP_Z) if( parser.mUpDirection == ColladaParser::UP_X)
pScene->mRootNode->mTransformation *= aiMatrix4x4( pScene->mRootNode->mTransformation *= aiMatrix4x4(
1, 0, 0, 0, 0, -1, 0, 0,
0, 0, 1, 0, 1, 0, 0, 0,
0, -1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
else if( parser.mUpDirection == ColladaParser::UP_Z)
pScene->mRootNode->mTransformation *= aiMatrix4x4(
1, 0, 0, 0,
0, 0, 1, 0,
0, -1, 0, 0,
0, 0, 0, 1);
}
// store all meshes // store all meshes
StoreSceneMeshes( pScene); StoreSceneMeshes( pScene);
@ -325,11 +332,11 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle ); out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle );
// ... some extension magic. FUCKING COLLADA. // ... some extension magic.
if (srcLight->mOuterAngle == 10e10f) if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
{ {
// ... some deprecation magic. FUCKING FCOLLADA. // ... some deprecation magic.
if (srcLight->mPenumbraAngle == 10e10f) if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
{ {
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess .... // Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
// epsilon chosen to be 0.1 // epsilon chosen to be 0.1
@ -382,7 +389,7 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
out->mClipPlaneNear = srcCamera->mZNear; out->mClipPlaneNear = srcCamera->mZNear;
// ... but for the rest some values are optional // ... but for the rest some values are optional
// and we need to compute the others in any combination. FUCKING COLLADA. // and we need to compute the others in any combination.
if (srcCamera->mAspect != 10e10f) if (srcCamera->mAspect != 10e10f)
out->mAspect = srcCamera->mAspect; out->mAspect = srcCamera->mAspect;
@ -466,7 +473,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
} }
else else
{ {
DefaultLogger::get()->warn( boost::str( boost::format( "Collada: No material specified for subgroup \"%s\" in geometry \"%s\".") % submesh.mMaterial % mid.mMeshOrController)); DefaultLogger::get()->warn( boost::str( boost::format( "Collada: No material specified for subgroup <%s> in geometry <%s>.") % submesh.mMaterial % mid.mMeshOrController));
if( !mid.mMaterials.empty() ) if( !mid.mMaterials.empty() )
meshMaterial = mid.mMaterials.begin()->second.mMatName; meshMaterial = mid.mMaterials.begin()->second.mMatName;
} }
@ -514,7 +521,10 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
// assign the material index // assign the material index
dstMesh->mMaterialIndex = matIdx; dstMesh->mMaterialIndex = matIdx;
dstMesh->mName = mid.mMeshOrController; if(dstMesh->mName.length == 0)
{
dstMesh->mName = mid.mMeshOrController;
}
} }
} }
} }
@ -535,6 +545,8 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
{ {
aiMesh* dstMesh = new aiMesh; aiMesh* dstMesh = new aiMesh;
dstMesh->mName = pSrcMesh->mName;
// count the vertices addressed by its faces // count the vertices addressed by its faces
const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace, const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace,
pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, 0); pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, 0);
@ -545,7 +557,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
std::copy( pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() + std::copy( pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() +
pStartVertex + numVertices, dstMesh->mVertices); pStartVertex + numVertices, dstMesh->mVertices);
// normals, if given. HACK: (thom) Due to the fucking Collada spec we never // normals, if given. HACK: (thom) Due to the glorious Collada spec we never
// know if we have the same number of normals as there are positions. So we // know if we have the same number of normals as there are positions. So we
// also ignore any vertex attribute if it has a different count // also ignore any vertex attribute if it has a different count
if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices) if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices)
@ -636,7 +648,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
throw DeadlyImportError( "Data type mismatch while resolving mesh joints"); throw DeadlyImportError( "Data type mismatch while resolving mesh joints");
// sanity check: we rely on the vertex weights always coming as pairs of BoneIndex-WeightIndex // sanity check: we rely on the vertex weights always coming as pairs of BoneIndex-WeightIndex
if( pSrcController->mWeightInputJoints.mOffset != 0 || pSrcController->mWeightInputWeights.mOffset != 1) if( pSrcController->mWeightInputJoints.mOffset != 0 || pSrcController->mWeightInputWeights.mOffset != 1)
throw DeadlyImportError( "Unsupported vertex_weight adresssing scheme. Fucking collada spec."); throw DeadlyImportError( "Unsupported vertex_weight addressing scheme. ");
// create containers to collect the weights for each bone // create containers to collect the weights for each bone
size_t numBones = jointNames.mStrings.size(); size_t numBones = jointNames.mStrings.size();
@ -967,7 +979,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
else if( subElement == "Z") else if( subElement == "Z")
entry.mSubElement = 2; entry.mSubElement = 2;
else else
DefaultLogger::get()->warn( boost::str( boost::format( "Unknown anim subelement \"%s\". Ignoring") % subElement)); DefaultLogger::get()->warn( boost::str( boost::format( "Unknown anim subelement <%s>. Ignoring") % subElement));
} else } else
{ {
// no subelement following, transformId is remaining string // no subelement following, transformId is remaining string
@ -1445,13 +1457,16 @@ void ColladaLoader::ConvertPath (aiString& ss)
ss.data[ss.length] = 0; ss.data[ss.length] = 0;
} }
// find and convert all %xyz special chars // find and convert all %xy special chars
char* out = ss.data; char* out = ss.data;
for( const char* it = ss.data; it != ss.data + ss.length; /**/ ) for( const char* it = ss.data; it != ss.data + ss.length; /**/ )
{ {
if( *it == '%' ) if( *it == '%' && (it + 3) < ss.data + ss.length )
{ {
size_t nbr = strtoul16( ++it, &it); // separate the number to avoid dragging in chars from behind into the parsing
char mychar[3] = { it[1], it[2], 0 };
size_t nbr = strtoul16( mychar);
it += 3;
*out++ = (char)(nbr & 0xFF); *out++ = (char)(nbr & 0xFF);
} else } else
{ {

View File

@ -234,6 +234,7 @@ protected:
std::vector<aiAnimation*> mAnims; std::vector<aiAnimation*> mAnims;
bool noSkeletonMesh; bool noSkeletonMesh;
bool ignoreUpDirection;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -140,7 +140,7 @@ void ColladaParser::ReadContents()
ReadStructure(); ReadStructure();
} else } else
{ {
DefaultLogger::get()->debug( boost::str( boost::format( "Ignoring global element \"%s\".") % mReader->getNodeName())); DefaultLogger::get()->debug( boost::str( boost::format( "Ignoring global element <%s>.") % mReader->getNodeName()));
SkipElement(); SkipElement();
} }
} else } else
@ -240,7 +240,7 @@ void ColladaParser::ReadAssetInfo()
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "asset") != 0) if( strcmp( mReader->getNodeName(), "asset") != 0)
ThrowException( "Expected end of \"asset\" element."); ThrowException( "Expected end of <asset> element.");
break; break;
} }
@ -271,7 +271,7 @@ void ColladaParser::ReadAnimationLibrary()
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "library_animations") != 0) if( strcmp( mReader->getNodeName(), "library_animations") != 0)
ThrowException( "Expected end of \"library_animations\" element."); ThrowException( "Expected end of <library_animations> element.");
break; break;
} }
@ -362,7 +362,7 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "animation") != 0) if( strcmp( mReader->getNodeName(), "animation") != 0)
ThrowException( "Expected end of \"animation\" element."); ThrowException( "Expected end of <animation> element.");
break; break;
} }
@ -425,7 +425,7 @@ void ColladaParser::ReadAnimationSampler( Collada::AnimationChannel& pChannel)
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "sampler") != 0) if( strcmp( mReader->getNodeName(), "sampler") != 0)
ThrowException( "Expected end of \"sampler\" element."); ThrowException( "Expected end of <sampler> element.");
break; break;
} }
@ -463,7 +463,7 @@ void ColladaParser::ReadControllerLibrary()
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "library_controllers") != 0) if( strcmp( mReader->getNodeName(), "library_controllers") != 0)
ThrowException( "Expected end of \"library_controllers\" element."); ThrowException( "Expected end of <library_controllers> element.");
break; break;
} }
@ -487,7 +487,7 @@ void ColladaParser::ReadController( Collada::Controller& pController)
else if( IsElement( "skin")) else if( IsElement( "skin"))
{ {
// read the mesh it refers to. According to the spec this could also be another // read the mesh it refers to. According to the spec this could also be another
// controller, but I refuse to implement every bullshit idea they've come up with // controller, but I refuse to implement every single idea they've come up with
int sourceIndex = GetAttribute( "source"); int sourceIndex = GetAttribute( "source");
pController.mMeshId = mReader->getAttributeValue( sourceIndex) + 1; pController.mMeshId = mReader->getAttributeValue( sourceIndex) + 1;
} }
@ -531,7 +531,7 @@ void ColladaParser::ReadController( Collada::Controller& pController)
if( strcmp( mReader->getNodeName(), "controller") == 0) if( strcmp( mReader->getNodeName(), "controller") == 0)
break; break;
else if( strcmp( mReader->getNodeName(), "skin") != 0) else if( strcmp( mReader->getNodeName(), "skin") != 0)
ThrowException( "Expected end of \"controller\" element."); ThrowException( "Expected end of <controller> element.");
} }
} }
} }
@ -554,7 +554,7 @@ void ColladaParser::ReadControllerJoints( Collada::Controller& pController)
// local URLS always start with a '#'. We don't support global URLs // local URLS always start with a '#'. We don't support global URLs
if( attrSource[0] != '#') if( attrSource[0] != '#')
ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\"") % attrSource)); ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\" in source attribute of <joints> data <input> element") % attrSource));
attrSource++; attrSource++;
// parse source URL to corresponding source // parse source URL to corresponding source
@ -563,7 +563,7 @@ void ColladaParser::ReadControllerJoints( Collada::Controller& pController)
else if( strcmp( attrSemantic, "INV_BIND_MATRIX") == 0) else if( strcmp( attrSemantic, "INV_BIND_MATRIX") == 0)
pController.mJointOffsetMatrixSource = attrSource; pController.mJointOffsetMatrixSource = attrSource;
else else
ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in joint data") % attrSemantic)); ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in <joints> data <input> element") % attrSemantic));
// skip inner data, if present // skip inner data, if present
if( !mReader->isEmptyElement()) if( !mReader->isEmptyElement())
@ -578,7 +578,7 @@ void ColladaParser::ReadControllerJoints( Collada::Controller& pController)
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "joints") != 0) if( strcmp( mReader->getNodeName(), "joints") != 0)
ThrowException( "Expected end of \"joints\" element."); ThrowException( "Expected end of <joints> element.");
break; break;
} }
@ -613,7 +613,7 @@ void ColladaParser::ReadControllerWeights( Collada::Controller& pController)
// local URLS always start with a '#'. We don't support global URLs // local URLS always start with a '#'. We don't support global URLs
if( attrSource[0] != '#') if( attrSource[0] != '#')
ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\"") % attrSource)); ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\" in source attribute of <vertex_weights> data <input> element") % attrSource));
channel.mAccessor = attrSource + 1; channel.mAccessor = attrSource + 1;
// parse source URL to corresponding source // parse source URL to corresponding source
@ -622,7 +622,7 @@ void ColladaParser::ReadControllerWeights( Collada::Controller& pController)
else if( strcmp( attrSemantic, "WEIGHT") == 0) else if( strcmp( attrSemantic, "WEIGHT") == 0)
pController.mWeightInputWeights = channel; pController.mWeightInputWeights = channel;
else else
ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in vertex_weight data") % attrSemantic)); ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in <vertex_weights> data <input> element") % attrSemantic));
// skip inner data, if present // skip inner data, if present
if( !mReader->isEmptyElement()) if( !mReader->isEmptyElement())
@ -636,7 +636,7 @@ void ColladaParser::ReadControllerWeights( Collada::Controller& pController)
for( std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) for( std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it)
{ {
if( *text == 0) if( *text == 0)
ThrowException( "Out of data while reading vcount"); ThrowException( "Out of data while reading <vcount>");
*it = strtoul10( text, &text); *it = strtoul10( text, &text);
numWeights += *it; numWeights += *it;
@ -656,11 +656,11 @@ void ColladaParser::ReadControllerWeights( Collada::Controller& pController)
for( std::vector< std::pair<size_t, size_t> >::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) for( std::vector< std::pair<size_t, size_t> >::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it)
{ {
if( *text == 0) if( *text == 0)
ThrowException( "Out of data while reading vertex_weights"); ThrowException( "Out of data while reading <vertex_weights>");
it->first = strtoul10( text, &text); it->first = strtoul10( text, &text);
SkipSpacesAndLineEnd( &text); SkipSpacesAndLineEnd( &text);
if( *text == 0) if( *text == 0)
ThrowException( "Out of data while reading vertex_weights"); ThrowException( "Out of data while reading <vertex_weights>");
it->second = strtoul10( text, &text); it->second = strtoul10( text, &text);
SkipSpacesAndLineEnd( &text); SkipSpacesAndLineEnd( &text);
} }
@ -676,7 +676,7 @@ void ColladaParser::ReadControllerWeights( Collada::Controller& pController)
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "vertex_weights") != 0) if( strcmp( mReader->getNodeName(), "vertex_weights") != 0)
ThrowException( "Expected end of \"vertex_weights\" element."); ThrowException( "Expected end of <vertex_weights> element.");
break; break;
} }
@ -712,7 +712,7 @@ void ColladaParser::ReadImageLibrary()
} }
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if( strcmp( mReader->getNodeName(), "library_images") != 0) if( strcmp( mReader->getNodeName(), "library_images") != 0)
ThrowException( "Expected end of \"library_images\" element."); ThrowException( "Expected end of <library_images> element.");
break; break;
} }
@ -838,7 +838,7 @@ void ColladaParser::ReadMaterialLibrary()
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "library_materials") != 0) if( strcmp( mReader->getNodeName(), "library_materials") != 0)
ThrowException( "Expected end of \"library_materials\" element."); ThrowException( "Expected end of <library_materials> element.");
break; break;
} }
@ -872,7 +872,7 @@ void ColladaParser::ReadLightLibrary()
} }
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if( strcmp( mReader->getNodeName(), "library_lights") != 0) if( strcmp( mReader->getNodeName(), "library_lights") != 0)
ThrowException( "Expected end of \"library_lights\" element."); ThrowException( "Expected end of <library_lights> element.");
break; break;
} }
@ -911,7 +911,7 @@ void ColladaParser::ReadCameraLibrary()
} }
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if( strcmp( mReader->getNodeName(), "library_cameras") != 0) if( strcmp( mReader->getNodeName(), "library_cameras") != 0)
ThrowException( "Expected end of \"library_cameras\" element."); ThrowException( "Expected end of <library_cameras> element.");
break; break;
} }
@ -947,7 +947,7 @@ void ColladaParser::ReadMaterial( Collada::Material& pMaterial)
} }
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if( strcmp( mReader->getNodeName(), "material") != 0) if( strcmp( mReader->getNodeName(), "material") != 0)
ThrowException( "Expected end of \"material\" element."); ThrowException( "Expected end of <material> element.");
break; break;
} }
@ -1097,9 +1097,6 @@ void ColladaParser::ReadEffectLibrary()
if( IsElement( "effect")) if( IsElement( "effect"))
{ {
// read ID. Do I have to repeat my ranting about "optional" attributes? // read ID. Do I have to repeat my ranting about "optional" attributes?
// Alex: .... no, not necessary. Please shut up and leave more space for
// me to complain about the fucking Collada spec with its fucking
// 'optional' attributes ...
int attrID = GetAttribute( "id"); int attrID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( attrID); std::string id = mReader->getAttributeValue( attrID);
@ -1115,7 +1112,7 @@ void ColladaParser::ReadEffectLibrary()
} }
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if( strcmp( mReader->getNodeName(), "library_effects") != 0) if( strcmp( mReader->getNodeName(), "library_effects") != 0)
ThrowException( "Expected end of \"library_effects\" element."); ThrowException( "Expected end of <library_effects> element.");
break; break;
} }
@ -1139,7 +1136,7 @@ void ColladaParser::ReadEffect( Collada::Effect& pEffect)
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "effect") != 0) if( strcmp( mReader->getNodeName(), "effect") != 0)
ThrowException( "Expected end of \"effect\" element."); ThrowException( "Expected end of <effect> element.");
break; break;
} }
@ -1496,6 +1493,13 @@ void ColladaParser::ReadGeometryLibrary()
Mesh* mesh = new Mesh; Mesh* mesh = new Mesh;
mMeshLibrary[id] = mesh; mMeshLibrary[id] = mesh;
// read the mesh name if it exists
const int nameIndex = TestAttribute("name");
if(nameIndex != -1)
{
mesh->mName = mReader->getAttributeValue(nameIndex);
}
// read on from there // read on from there
ReadGeometry( mesh); ReadGeometry( mesh);
} else } else
@ -1507,7 +1511,7 @@ void ColladaParser::ReadGeometryLibrary()
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "library_geometries") != 0) if( strcmp( mReader->getNodeName(), "library_geometries") != 0)
ThrowException( "Expected end of \"library_geometries\" element."); ThrowException( "Expected end of <library_geometries> element.");
break; break;
} }
@ -1538,7 +1542,7 @@ void ColladaParser::ReadGeometry( Collada::Mesh* pMesh)
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "geometry") != 0) if( strcmp( mReader->getNodeName(), "geometry") != 0)
ThrowException( "Expected end of \"geometry\" element."); ThrowException( "Expected end of <geometry> element.");
break; break;
} }
@ -1590,7 +1594,7 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
} else } else
{ {
// everything else should be punished // everything else should be punished
ThrowException( "Expected end of \"mesh\" element."); ThrowException( "Expected end of <mesh> element.");
} }
} }
} }
@ -1613,7 +1617,7 @@ void ColladaParser::ReadSource()
} }
else if( IsElement( "technique_common")) else if( IsElement( "technique_common"))
{ {
// I don't fucking care for your profiles bullshit // I don't care for your profiles
} }
else if( IsElement( "accessor")) else if( IsElement( "accessor"))
{ {
@ -1637,7 +1641,7 @@ void ColladaParser::ReadSource()
} else } else
{ {
// everything else should be punished // everything else should be punished
ThrowException( "Expected end of \"source\" element."); ThrowException( "Expected end of <source> element.");
} }
} }
} }
@ -1716,7 +1720,7 @@ void ColladaParser::ReadAccessor( const std::string& pID)
int attrSource = GetAttribute( "source"); int attrSource = GetAttribute( "source");
const char* source = mReader->getAttributeValue( attrSource); const char* source = mReader->getAttributeValue( attrSource);
if( source[0] != '#') if( source[0] != '#')
ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\".") % source)); ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\" in source attribute of <accessor> element.") % source));
int attrCount = GetAttribute( "count"); int attrCount = GetAttribute( "count");
unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( attrCount); unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( attrCount);
int attrOffset = TestAttribute( "offset"); int attrOffset = TestAttribute( "offset");
@ -1901,7 +1905,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
for( unsigned int a = 0; a < numPrimitives; a++) for( unsigned int a = 0; a < numPrimitives; a++)
{ {
if( *content == 0) if( *content == 0)
ThrowException( "Expected more values while reading vcount contents."); ThrowException( "Expected more values while reading <vcount> contents.");
// read a number // read a number
vcount.push_back( (size_t) strtoul10( content, &content)); vcount.push_back( (size_t) strtoul10( content, &content));
// skip whitespace after it // skip whitespace after it
@ -1949,7 +1953,7 @@ void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels)
int attrSource = GetAttribute( "source"); int attrSource = GetAttribute( "source");
const char* source = mReader->getAttributeValue( attrSource); const char* source = mReader->getAttributeValue( attrSource);
if( source[0] != '#') if( source[0] != '#')
ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\".") % source)); ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\" in source attribute of <input> element.") % source));
channel.mAccessor = source+1; // skipping the leading #, hopefully the remaining text is the accessor ID only channel.mAccessor = source+1; // skipping the leading #, hopefully the remaining text is the accessor ID only
// read index offset, if per-index <input> // read index offset, if per-index <input>
@ -1963,7 +1967,7 @@ void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels)
if(attrSet > -1){ if(attrSet > -1){
attrSet = mReader->getAttributeValueAsInt( attrSet); attrSet = mReader->getAttributeValueAsInt( attrSet);
if(attrSet < 0) if(attrSet < 0)
ThrowException( boost::str( boost::format( "Invalid index \"%i\" for set attribute") % (attrSet))); ThrowException( boost::str( boost::format( "Invalid index \"%i\" in set attribute of <input> element") % (attrSet)));
channel.mIndex = attrSet; channel.mIndex = attrSet;
} }
@ -2581,18 +2585,18 @@ void ColladaParser::ReadScene()
{ {
// should be the first and only occurence // should be the first and only occurence
if( mRootNode) if( mRootNode)
ThrowException( "Invalid scene containing multiple root nodes"); ThrowException( "Invalid scene containing multiple root nodes in <instance_visual_scene> element");
// read the url of the scene to instance. Should be of format "#some_name" // read the url of the scene to instance. Should be of format "#some_name"
int urlIndex = GetAttribute( "url"); int urlIndex = GetAttribute( "url");
const char* url = mReader->getAttributeValue( urlIndex); const char* url = mReader->getAttributeValue( urlIndex);
if( url[0] != '#') if( url[0] != '#')
ThrowException( "Unknown reference format"); ThrowException( "Unknown reference format in <instance_visual_scene> element");
// find the referred scene, skip the leading # // find the referred scene, skip the leading #
NodeLibrary::const_iterator sit = mNodeLibrary.find( url+1); NodeLibrary::const_iterator sit = mNodeLibrary.find( url+1);
if( sit == mNodeLibrary.end()) if( sit == mNodeLibrary.end())
ThrowException( "Unable to resolve visual_scene reference \"" + std::string(url) + "\"."); ThrowException( "Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
mRootNode = sit->second; mRootNode = sit->second;
} else { } else {
SkipElement(); SkipElement();
@ -2644,14 +2648,14 @@ void ColladaParser::TestOpening( const char* pName)
{ {
// read element start // read element start
if( !mReader->read()) if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while beginning of \"%s\" element.") % pName)); ThrowException( boost::str( boost::format( "Unexpected end of file while beginning of <%s> element.") % pName));
// whitespace in front is ok, just read again if found // whitespace in front is ok, just read again if found
if( mReader->getNodeType() == irr::io::EXN_TEXT) if( mReader->getNodeType() == irr::io::EXN_TEXT)
if( !mReader->read()) if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while reading beginning of \"%s\" element.") % pName)); ThrowException( boost::str( boost::format( "Unexpected end of file while reading beginning of <%s> element.") % pName));
if( mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp( mReader->getNodeName(), pName) != 0) if( mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp( mReader->getNodeName(), pName) != 0)
ThrowException( boost::str( boost::format( "Expected start of \"%s\" element.") % pName)); ThrowException( boost::str( boost::format( "Expected start of <%s> element.") % pName));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -2664,15 +2668,15 @@ void ColladaParser::TestClosing( const char* pName)
// if not, read some more // if not, read some more
if( !mReader->read()) if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName)); ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of <%s> element.") % pName));
// whitespace in front is ok, just read again if found // whitespace in front is ok, just read again if found
if( mReader->getNodeType() == irr::io::EXN_TEXT) if( mReader->getNodeType() == irr::io::EXN_TEXT)
if( !mReader->read()) if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName)); ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of <%s> element.") % pName));
// but this has the be the closing tag, or we're lost // but this has the be the closing tag, or we're lost
if( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0) if( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0)
ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % pName)); ThrowException( boost::str( boost::format( "Expected end of <%s> element.") % pName));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -2684,7 +2688,7 @@ int ColladaParser::GetAttribute( const char* pAttr) const
return index; return index;
// attribute not found -> throw an exception // attribute not found -> throw an exception
ThrowException( boost::str( boost::format( "Expected attribute \"%s\" at element \"%s\".") % pAttr % mReader->getNodeName())); ThrowException( boost::str( boost::format( "Expected attribute \"%s\" for element <%s>.") % pAttr % mReader->getNodeName()));
return -1; return -1;
} }

View File

@ -60,6 +60,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
#include "BaseProcess.h" #include "BaseProcess.h"
#include "Importer.h" // need this for GetPostProcessingStepInstanceList() #include "Importer.h" // need this for GetPostProcessingStepInstanceList()
#include "JoinVerticesProcess.h"
#include "MakeVerboseFormat.h" #include "MakeVerboseFormat.h"
#include "ConvertToLHProcess.h" #include "ConvertToLHProcess.h"
@ -73,6 +74,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
void ExportSceneCollada(const char*,IOSystem*, const aiScene*); void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
void ExportSceneObj(const char*,IOSystem*, const aiScene*); void ExportSceneObj(const char*,IOSystem*, const aiScene*);
void ExportSceneSTL(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 ExportScenePly(const char*,IOSystem*, const aiScene*);
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {} void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
@ -85,13 +87,17 @@ Exporter::ExportFormatEntry gExporters[] =
#endif #endif
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj), Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
aiProcess_GenNormals /*| aiProcess_PreTransformVertices */),
#endif #endif
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER #ifndef ASSIMP_BUILD_NO_STL_EXPORTER
Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL, Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
), ),
Exporter::ExportFormatEntry( "stlb", "Stereolithography(binary)", "stlb" , &ExportSceneSTLBinary,
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
),
#endif #endif
#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER #ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
@ -196,7 +202,7 @@ bool Exporter :: IsDefaultIOHandler() const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ) const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int )
{ {
if (pimpl->blob) { if (pimpl->blob) {
delete pimpl->blob; delete pimpl->blob;
@ -259,6 +265,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
// If the input scene is not in verbose format, but there is at least postprocessing step that relies on it, // If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
// we need to run the MakeVerboseFormat step first. // we need to run the MakeVerboseFormat step first.
bool must_join_again = false;
if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
bool verbosify = false; bool verbosify = false;
@ -276,6 +283,10 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
MakeVerboseFormatProcess proc; MakeVerboseFormatProcess proc;
proc.Execute(scenecopy.get()); proc.Execute(scenecopy.get());
if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
must_join_again = true;
}
} }
} }
@ -320,6 +331,11 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
privOut->mPPStepsApplied |= pp; privOut->mPPStepsApplied |= pp;
} }
if(must_join_again) {
JoinVerticesProcess proc;
proc.Execute(scenecopy.get());
}
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get()); exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
} }
catch (DeadlyExportError& err) { catch (DeadlyExportError& err) {

View File

@ -232,7 +232,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
// compute length based on type and check against the stored value // compute length based on type and check against the stored value
if(encoding == 0) { if(encoding == 0) {
uint32_t stride; uint32_t stride = 0;
switch(type) switch(type)
{ {
case 'f': case 'f':
@ -248,6 +248,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
default: default:
ai_assert(false); ai_assert(false);
}; };
ai_assert(stride > 0);
if(length * stride != comp_len) { if(length * stride != comp_len) {
TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor); TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
} }
@ -380,7 +381,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
} }
uint32_t offset = 0x1b; //uint32_t offset = 0x1b;
const char* cursor = input + 0x1b; const char* cursor = input + 0x1b;

View File

@ -97,9 +97,9 @@ public:
public: public:
Converter(aiScene* out, const Document& doc) Converter(aiScene* out, const Document& doc)
: out(out) : defaultMaterialIndex()
, out(out)
, doc(doc) , doc(doc)
, defaultMaterialIndex()
{ {
// animations need to be converted first since this will // animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed // populate the node_anim_chain_bits map, which is needed
@ -419,6 +419,8 @@ private:
return "Scaling"; return "Scaling";
case TransformationComp_ScalingPivotInverse: case TransformationComp_ScalingPivotInverse:
return "ScalingPivotInverse"; return "ScalingPivotInverse";
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
break;
} }
ai_assert(false); ai_assert(false);
@ -454,6 +456,8 @@ private:
return "Lcl Scaling"; return "Lcl Scaling";
case TransformationComp_ScalingPivotInverse: case TransformationComp_ScalingPivotInverse:
return "ScalingPivotInverse"; return "ScalingPivotInverse";
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
break;
} }
ai_assert(false); ai_assert(false);
@ -544,6 +548,10 @@ private:
ai_assert(false); ai_assert(false);
} }
ai_assert((order[0] >= 0) && (order[0] <= 2));
ai_assert((order[1] >= 0) && (order[1] <= 2));
ai_assert((order[2] >= 0) && (order[2] <= 2));
if(!is_id[order[0]]) { if(!is_id[order[0]]) {
out = temp[order[0]]; out = temp[order[0]];
} }
@ -1167,7 +1175,6 @@ private:
ai_assert(cluster); ai_assert(cluster);
const WeightIndexArray& indices = cluster->GetIndices(); const WeightIndexArray& indices = cluster->GetIndices();
const WeightArray& weights = cluster->GetWeights();
if(indices.empty()) { if(indices.empty()) {
continue; continue;
@ -1194,7 +1201,7 @@ private:
count_out_indices.push_back(0); count_out_indices.push_back(0);
for(unsigned int i = 0; i < count; ++i) { for(unsigned int i = 0; i < count; ++i) {
if (no_mat_check || mats[geo.FaceForVertexIndex(out_idx[i])] == materialIndex) { if (no_mat_check || static_cast<size_t>(mats[geo.FaceForVertexIndex(out_idx[i])]) == materialIndex) {
if (index_out_indices.back() == no_index_sentinel) { if (index_out_indices.back() == no_index_sentinel) {
index_out_indices.back() = out_indices.size(); index_out_indices.back() = out_indices.size();
@ -1608,6 +1615,9 @@ private:
case FileGlobalSettings::FrameRate_CUSTOM: case FileGlobalSettings::FrameRate_CUSTOM:
return customFPSVal; return customFPSVal;
case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings
break;
} }
ai_assert(false); ai_assert(false);
@ -1838,7 +1848,7 @@ private:
}} }}
#endif #endif
const AnimationCurveNode* curve_node; const AnimationCurveNode* curve_node = NULL;
BOOST_FOREACH(const AnimationCurveNode* node, curves) { BOOST_FOREACH(const AnimationCurveNode* node, curves) {
ai_assert(node); ai_assert(node);

View File

@ -231,8 +231,8 @@ Object::~Object()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
FileGlobalSettings::FileGlobalSettings(const Document& doc, boost::shared_ptr<const PropertyTable> props) FileGlobalSettings::FileGlobalSettings(const Document& doc, boost::shared_ptr<const PropertyTable> props)
: doc(doc) : props(props)
, props(props) , doc(doc)
{ {
} }
@ -579,7 +579,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
for (size_t i = 0; i < c; ++i) { for (size_t i = 0; i < c; ++i) {
ai_assert(classnames[i]); ai_assert(classnames[i]);
if(std::distance(key.begin(),key.end()) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) { if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) {
obtype = NULL; obtype = NULL;
break; break;
} }

View File

@ -50,8 +50,8 @@ namespace Util {
/* DOM/Parse error reporting - does not return */ /* DOM/Parse error reporting - does not return */
void DOMError(const std::string& message, const Token& token); AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
void DOMError(const std::string& message, const Element* element = NULL); AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
// does return // does return
void DOMWarning(const std::string& message, const Token& token); void DOMWarning(const std::string& message, const Token& token);

View File

@ -51,13 +51,13 @@ namespace FBX {
struct ImportSettings struct ImportSettings
{ {
ImportSettings() ImportSettings()
: readAllLayers(true) : strictMode(true)
, readAllLayers(true)
, readAllMaterials() , readAllMaterials()
, readMaterials(true) , readMaterials(true)
, readCameras(true) , readCameras(true)
, readLights(true) , readLights(true)
, readAnimations(true) , readAnimations(true)
, strictMode(true)
, readWeights(true) , readWeights(true)
, preservePivots(true) , preservePivots(true)
, optimizeEmptyAnimationCurves(true) , optimizeEmptyAnimationCurves(true)

View File

@ -512,7 +512,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
ai_assert(data + comp_len == end); ai_assert(data + comp_len == end);
// determine the length of the uncompressed data by looking at the type signature // determine the length of the uncompressed data by looking at the type signature
uint32_t stride; uint32_t stride = 0;
switch(type) switch(type)
{ {
case 'f': case 'f':

View File

@ -72,6 +72,9 @@ const char* TokenTypeString(TokenType t)
case TokenType_KEY: case TokenType_KEY:
return "TOK_KEY"; return "TOK_KEY";
case TokenType_BINARY_DATA:
return "TOK_BINARY_DATA";
} }
ai_assert(false); ai_assert(false);

View File

@ -245,7 +245,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
// directly on the vertex between two segments. // directly on the vertex between two segments.
if (!intersected_boundary_points.empty() && intersected_boundary_segments.back()==i-1 ) { if (!intersected_boundary_points.empty() && intersected_boundary_segments.back()==i-1 ) {
const IfcVector3 diff = intersected_boundary_points.back() - p; const IfcVector3 diff = intersected_boundary_points.back() - p;
if(IfcVector3((diff.x, diff.y)).SquareLength() < 1e-7) { if(IfcVector2(diff.x, diff.y).SquareLength() < 1e-7) {
continue; continue;
} }
} }
@ -381,7 +381,8 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
unsigned int newcount = 0; unsigned int newcount = 0;
bool was_outside_boundary = !PointInPoly(proj * in[vidx], profile->verts); bool was_outside_boundary = !PointInPoly(proj * in[vidx], profile->verts);
size_t last_intersected_boundary_segment; // used any more?
//size_t last_intersected_boundary_segment;
IfcVector3 last_intersected_boundary_point; IfcVector3 last_intersected_boundary_point;
bool extra_point_flag = false; bool extra_point_flag = false;

View File

@ -137,8 +137,6 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
const size_t outer_polygon_size = *outer_polygon_it; const size_t outer_polygon_size = *outer_polygon_it;
const IfcVector3& master_normal = normals[std::distance(begin, outer_polygon_it)]; const IfcVector3& master_normal = normals[std::distance(begin, outer_polygon_it)];
const IfcVector3& master_normal_norm = IfcVector3(master_normal).Normalize();
// Generate fake openings to meet the interface for the quadrulate // Generate fake openings to meet the interface for the quadrulate
// algorithm. It boils down to generating small boxes given the // algorithm. It boils down to generating small boxes given the
@ -329,7 +327,6 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv
} }
const std::vector<IfcVector3>& in = result.verts; const std::vector<IfcVector3>& in = result.verts;
const size_t size=in.size();
const unsigned int cnt_segments = 16; const unsigned int cnt_segments = 16;
const IfcFloat deltaAngle = AI_MATH_TWO_PI/cnt_segments; const IfcFloat deltaAngle = AI_MATH_TWO_PI/cnt_segments;
@ -476,12 +473,12 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
IfcVector3 nor; IfcVector3 nor;
// The input polygon is arbitrarily shaped, therefore we might need some tries // The input polygon is arbitrarily shaped, therefore we might need some tries
// until we find a suitable normal. Note that Newells algorithm would give // until we find a suitable normal. Note that Newell's algorithm would give
// a more robust result, but this variant also gives us a suitable first // a more robust result, but this variant also gives us a suitable first
// axis for the 2D coordinate space on the polygon plane, exploiting the // axis for the 2D coordinate space on the polygon plane, exploiting the
// fact that the input polygon is nearly always a quad. // fact that the input polygon is nearly always a quad.
bool done = false; bool done = false;
size_t base = 0, i, j; size_t i, j;
for (i = 0; !done && i < s-2; done || ++i) { for (i = 0; !done && i < s-2; done || ++i) {
for (j = i+1; j < s-1; ++j) { for (j = i+1; j < s-1; ++j) {
nor = -((out[i]-any_point)^(out[j]-any_point)); nor = -((out[i]-any_point)^(out[j]-any_point));

View File

@ -48,7 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iterator> #include <iterator>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include "../contrib/unzip/unzip.h" #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
# include "../contrib/unzip/unzip.h"
#endif
#include "IFCLoader.h" #include "IFCLoader.h"
#include "STEPFileReader.h" #include "STEPFileReader.h"
@ -169,8 +171,10 @@ void IFCImporter::InternReadFile( const std::string& pFile,
ThrowException("Could not open file for reading"); ThrowException("Could not open file for reading");
} }
// if this is a ifczip file, decompress its contents first // if this is a ifczip file, decompress its contents first
if(GetExtension(pFile) == "ifczip") { if(GetExtension(pFile) == "ifczip") {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
unzFile zip = unzOpen( pFile.c_str() ); unzFile zip = unzOpen( pFile.c_str() );
if(zip == NULL) { if(zip == NULL) {
ThrowException("Could not open ifczip file for reading, unzip failed"); ThrowException("Could not open ifczip file for reading, unzip failed");
@ -188,32 +192,50 @@ void IFCImporter::InternReadFile( const std::string& pFile,
} }
// search file (same name as the IFCZIP except for the file extension) and place file pointer there // search file (same name as the IFCZIP except for the file extension) and place file pointer there
if ( unzLocateFile( zip, fileName.c_str(), 0 ) == UNZ_OK )
{
// get file size, etc.
unz_file_info fileInfo;
unzGetCurrentFileInfo( zip , &fileInfo, 0, 0, 0, 0, 0, 0 );
uint8_t* buff = new uint8_t[fileInfo.uncompressed_size]; if(UNZ_OK == unzGoToFirstFile(zip)) {
do {
//
LogInfo("Decompressing IFCZIP file"); // get file size, etc.
unz_file_info fileInfo;
char filename[256];
unzGetCurrentFileInfo( zip , &fileInfo, filename, sizeof(filename), 0, 0, 0, 0 );
unzOpenCurrentFile( zip ); if (GetExtension(filename) != "ifc") {
const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size); continue;
size_t filesize = fileInfo.uncompressed_size; }
if ( ret < 0 || size_t(ret) != filesize )
{ uint8_t* buff = new uint8_t[fileInfo.uncompressed_size];
delete[] buff;
ThrowException("Failed to decompress IFC ZIP file"); LogInfo("Decompressing IFCZIP file");
}
unzCloseCurrentFile( zip ); unzOpenCurrentFile( zip );
stream.reset(new MemoryIOStream(buff,fileInfo.uncompressed_size,true)); const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size);
size_t filesize = fileInfo.uncompressed_size;
if ( ret < 0 || size_t(ret) != filesize )
{
delete[] buff;
ThrowException("Failed to decompress IFC ZIP file");
}
unzCloseCurrentFile( zip );
stream.reset(new MemoryIOStream(buff,fileInfo.uncompressed_size,true));
break;
if (unzGoToNextFile(zip) == UNZ_END_OF_LIST_OF_FILE) {
ThrowException("Found no IFC file member in IFCZIP file (1)");
}
} while(true);
} }
else { else {
ThrowException("Found no IFC file member in IFCZIP file"); ThrowException("Found no IFC file member in IFCZIP file (2)");
} }
unzClose(zip); unzClose(zip);
#else
ThrowException("Could not open ifczip file for reading, assimp was built without ifczip support");
#endif
} }
boost::scoped_ptr<STEP::DB> db(STEP::ReadFileHeader(stream)); boost::scoped_ptr<STEP::DB> db(STEP::ReadFileHeader(stream));
@ -244,7 +266,7 @@ void IFCImporter::InternReadFile( const std::string& pFile,
// tell the reader for which types we need to simulate STEPs reverse indices // tell the reader for which types we need to simulate STEPs reverse indices
static const char* const inverse_indices_to_track[] = { static const char* const inverse_indices_to_track[] = {
"ifcrelcontainedinspatialstructure", "ifcrelaggregates", "ifcrelvoidselement", "ifcstyleditem" "ifcrelcontainedinspatialstructure", "ifcrelaggregates", "ifcrelvoidselement", "ifcreldefinesbyproperties", "ifcpropertyset", "ifcstyleditem"
}; };
// feed the IFC schema into the reader and pre-parse all lines // feed the IFC schema into the reader and pre-parse all lines
@ -506,7 +528,7 @@ struct RateRepresentationPredicate {
return -3; return -3;
} }
// give strong preference to extruded geometry // give strong preference to extruded geometry.
if (r == "SweptSolid") { if (r == "SweptSolid") {
return -10; return -10;
} }
@ -577,6 +599,86 @@ void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector<
AssignAddedMeshes(meshes,nd,conv); AssignAddedMeshes(meshes,nd,conv);
} }
typedef std::map<std::string, std::string> Metadata;
// ------------------------------------------------------------------------------------------------
void ProcessMetadata(const ListOf< Lazy< IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
const std::string& prefix = "",
unsigned int nest = 0)
{
BOOST_FOREACH(const IfcProperty& property, set) {
const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
if (const IfcPropertySingleValue* const singleValue = property.ToPtr<IfcPropertySingleValue>()) {
if (singleValue->NominalValue) {
if (const EXPRESS::STRING* str = singleValue->NominalValue.Get()->ToPtr<EXPRESS::STRING>()) {
std::string value = static_cast<std::string>(*str);
properties[key]=value;
}
else if (const EXPRESS::REAL* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::REAL>()) {
float value = static_cast<float>(*val);
std::stringstream s;
s << value;
properties[key]=s.str();
}
else if (const EXPRESS::INTEGER* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::INTEGER>()) {
int64_t value = static_cast<int64_t>(*val);
std::stringstream s;
s << value;
properties[key]=s.str();
}
}
}
else if (const IfcPropertyListValue* const listValue = property.ToPtr<IfcPropertyListValue>()) {
std::stringstream ss;
ss << "[";
unsigned index=0;
BOOST_FOREACH(const IfcValue::Out& v, listValue->ListValues) {
if (!v) continue;
if (const EXPRESS::STRING* str = v->ToPtr<EXPRESS::STRING>()) {
std::string value = static_cast<std::string>(*str);
ss << "'" << value << "'";
}
else if (const EXPRESS::REAL* val = v->ToPtr<EXPRESS::REAL>()) {
float value = static_cast<float>(*val);
ss << value;
}
else if (const EXPRESS::INTEGER* val = v->ToPtr<EXPRESS::INTEGER>()) {
int64_t value = static_cast<int64_t>(*val);
ss << value;
}
if (index+1<listValue->ListValues.size()) {
ss << ",";
}
index++;
}
ss << "]";
properties[key]=ss.str();
}
else if (const IfcComplexProperty* const complexProp = property.ToPtr<IfcComplexProperty>()) {
if(nest > 2) { // mostly arbitrary limit to prevent stack overflow vulnerabilities
IFCImporter::LogError("maximum nesting level for IfcComplexProperty reached, skipping this property.");
}
else {
ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1);
}
}
else {
properties[key]="";
}
}
}
// ------------------------------------------------------------------------------------------------
void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData& conv, Metadata& properties)
{
if (const IfcRelDefinesByProperties* const pset = conv.db.GetObject(relDefinesByPropertiesID)->ToPtr<IfcRelDefinesByProperties>()) {
if (const IfcPropertySet* const set = conv.db.GetObject(pset->RelatingPropertyDefinition->GetID())->ToPtr<IfcPropertySet>()) {
ProcessMetadata(set->HasProperties, conv, properties);
}
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, ConversionData& conv, std::vector<TempOpening>* collect_openings = NULL) aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, ConversionData& conv, std::vector<TempOpening>* collect_openings = NULL)
{ {
@ -602,6 +704,42 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId); nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId);
nd->mParent = parent; nd->mParent = parent;
conv.already_processed.insert(el.GetID());
// check for node metadata
STEP::DB::RefMapRange children = refs.equal_range(el.GetID());
if (children.first!=refs.end()) {
Metadata properties;
if (children.first==children.second) {
// handles single property set
ProcessMetadata((*children.first).second, conv, properties);
}
else {
// handles multiple property sets (currently all property sets are merged,
// which may not be the best solution in the long run)
for (STEP::DB::RefMap::const_iterator it=children.first; it!=children.second; ++it) {
ProcessMetadata((*it).second, conv, properties);
}
}
if (!properties.empty()) {
aiMetadata* data = new aiMetadata();
data->mNumProperties = properties.size();
data->mKeys = new aiString*[data->mNumProperties]();
data->mValues = new aiString*[data->mNumProperties]();
unsigned int i = 0;
BOOST_FOREACH(const Metadata::value_type& kv, properties) {
data->mKeys[i] = new aiString(kv.first);
if (kv.second.length() > 0) {
data->mValues[i] = new aiString(kv.second);
}
++i;
}
nd->mMetaData = data;
}
}
if(el.ObjectPlacement) { if(el.ObjectPlacement) {
ResolveObjectPlacement(nd->mTransformation,el.ObjectPlacement.Get(),conv); ResolveObjectPlacement(nd->mTransformation,el.ObjectPlacement.Get(),conv);
} }
@ -620,15 +758,24 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
STEP::DB::RefMapRange range = refs.equal_range(el.GetID()); STEP::DB::RefMapRange range = refs.equal_range(el.GetID());
for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) { for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) {
// skip over meshes that have already been processed before. This is strictly necessary
// because the reverse indices also include references contained in argument lists and
// therefore every element has a back-reference hold by its parent.
if (conv.already_processed.find((*range2.first).second) != conv.already_processed.end()) {
continue;
}
const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second); const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second);
// handle regularly-contained elements // handle regularly-contained elements
if(const IfcRelContainedInSpatialStructure* const cont = obj->ToPtr<IfcRelContainedInSpatialStructure>()) { if(const IfcRelContainedInSpatialStructure* const cont = obj->ToPtr<IfcRelContainedInSpatialStructure>()) {
if(cont->RelatingStructure->GetID() != el.GetID()) {
continue;
}
BOOST_FOREACH(const IfcProduct& pro, cont->RelatedElements) { BOOST_FOREACH(const IfcProduct& pro, cont->RelatedElements) {
if(const IfcOpeningElement* const open = pro.ToPtr<IfcOpeningElement>()) { if(const IfcOpeningElement* const open = pro.ToPtr<IfcOpeningElement>()) {
// IfcOpeningElement is handled below. Sadly we can't use it here as is: // IfcOpeningElement is handled below. Sadly we can't use it here as is:
// The docs say that opening elements are USUALLY attached to building storeys // The docs say that opening elements are USUALLY attached to building storey,
// but we want them for the building elements to which they belong to. // but we want them for the building elements to which they belong.
continue; continue;
} }
@ -679,7 +826,14 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
} }
for(;range.first != range.second; ++range.first) { for(;range.first != range.second; ++range.first) {
// see note in loop above
if (conv.already_processed.find((*range.first).second) != conv.already_processed.end()) {
continue;
}
if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) { if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
if(aggr->RelatingObject->GetID() != el.GetID()) {
continue;
}
// move aggregate elements to a separate node since they are semantically different than elements that are just 'contained' // move aggregate elements to a separate node since they are semantically different than elements that are just 'contained'
std::auto_ptr<aiNode> nd_aggr(new aiNode()); std::auto_ptr<aiNode> nd_aggr(new aiNode());
@ -725,6 +879,8 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
throw; throw;
} }
ai_assert(conv.already_processed.find(el.GetID()) != conv.already_processed.end());
conv.already_processed.erase(conv.already_processed.find(el.GetID()));
return nd.release(); return nd.release();
} }

View File

@ -603,7 +603,6 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
const IfcVector2& m0, const IfcVector2& m1, const IfcVector2& m0, const IfcVector2& m1,
IfcVector2& out0, IfcVector2& out1) IfcVector2& out0, IfcVector2& out1)
{ {
const IfcVector2& m0_to_m1 = m1 - m0;
const IfcVector2& n0_to_n1 = n1 - n0; const IfcVector2& n0_to_n1 = n1 - n0;
const IfcVector2& n0_to_m0 = m0 - n0; const IfcVector2& n0_to_m0 = m0 - n0;
@ -898,14 +897,13 @@ size_t CloseWindows(ContourVector& contours,
ai_assert((*it).skiplist.size() == (*it).contour.size()); ai_assert((*it).skiplist.size() == (*it).contour.size());
SkipList::const_iterator skipbegin = (*it).skiplist.begin(), skipend = (*it).skiplist.end(); SkipList::const_iterator skipbegin = (*it).skiplist.begin();
curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4); curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4);
curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size()); curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size());
// XXX this algorithm is really a bit inefficient - both in terms // XXX this algorithm is really a bit inefficient - both in terms
// of constant factor and of asymptotic runtime. // of constant factor and of asymptotic runtime.
size_t vstart = curmesh.verts.size();
std::vector<bool>::const_iterator skipit = skipbegin; std::vector<bool>::const_iterator skipit = skipbegin;
IfcVector3 start0; IfcVector3 start0;
@ -991,10 +989,10 @@ size_t CloseWindows(ContourVector& contours,
} }
} }
} }
/*
BOOST_FOREACH(TempOpening* opening, refs) { BOOST_FOREACH(TempOpening* opening, refs) {
//opening->wallPoints.clear(); //opening->wallPoints.clear();
} }*/
} }
else { else {
@ -1146,7 +1144,6 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
bool generate_connection_geometry, bool generate_connection_geometry,
const IfcVector3& wall_extrusion_axis) const IfcVector3& wall_extrusion_axis)
{ {
std::vector<IfcVector3>& out = curmesh.verts;
OpeningRefVector contours_to_openings; OpeningRefVector contours_to_openings;
// Try to derive a solid base plane within the current surface for use as // Try to derive a solid base plane within the current surface for use as
@ -1175,7 +1172,6 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
IfcVector3 wall_extrusion_axis_norm = wall_extrusion_axis; IfcVector3 wall_extrusion_axis_norm = wall_extrusion_axis;
wall_extrusion_axis_norm.Normalize(); wall_extrusion_axis_norm.Normalize();
size_t c = 0;
BOOST_FOREACH(TempOpening& opening,openings) { BOOST_FOREACH(TempOpening& opening,openings) {
// extrusionDir may be 0,0,0 on case where the opening mesh is not an // extrusionDir may be 0,0,0 on case where the opening mesh is not an

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -208,6 +208,8 @@ struct ConversionData
// for later processing by a parent, which is a wall. // for later processing by a parent, which is a wall.
std::vector<TempOpening>* apply_openings; std::vector<TempOpening>* apply_openings;
std::vector<TempOpening>* collect_openings; std::vector<TempOpening>* collect_openings;
std::set<uint64_t> already_processed;
}; };

View File

@ -160,9 +160,6 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
# include "IFCLoader.h" # include "IFCLoader.h"
#endif #endif
#ifndef ASSIMP_BUILD_NO_M3_IMPORTER
# include "M3Importer.h"
#endif
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER #ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
# include "XGLLoader.h" # include "XGLLoader.h"
#endif #endif
@ -288,9 +285,6 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER) #if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
out.push_back( new IFCImporter() ); out.push_back( new IFCImporter() );
#endif #endif
#if ( !defined ASSIMP_BUILD_NO_M3_IMPORTER )
out.push_back( new M3::M3Importer() );
#endif
#if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER ) #if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
out.push_back( new XGLImporter() ); out.push_back( new XGLImporter() );
#endif #endif

View File

@ -448,8 +448,8 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
if ((*cur_x).time == (*cur_y).time && (*cur_x).time == (*cur_z).time ) { if ((*cur_x).time == (*cur_y).time && (*cur_x).time == (*cur_z).time ) {
// we have a keyframe for all of them defined .. great, // we have a keyframe for all of them defined .. this means
// we don't need to fucking interpolate here ... // we don't need to interpolate here.
fill.mTime = (*cur_x).time; fill.mTime = (*cur_x).time;
fill.mValue.x = (*cur_x).value; fill.mValue.x = (*cur_x).value;

View File

@ -467,6 +467,10 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
for (; begin != end; ++begin) { for (; begin != end; ++begin) {
aiFace& face = *begin; aiFace& face = *begin;
if(face.mNumIndices < 3) {
continue;
}
// LWO doc: "the normal is defined as the cross product of the first and last edges" // LWO doc: "the normal is defined as the cross product of the first and last edges"
aiVector3D* pV1 = mesh->mVertices + face.mIndices[0]; aiVector3D* pV1 = mesh->mVertices + face.mIndices[0];
aiVector3D* pV2 = mesh->mVertices + face.mIndices[1]; aiVector3D* pV2 = mesh->mVertices + face.mIndices[1];

View File

@ -464,7 +464,7 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
std::string tmp; std::string tmp;
if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/') if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
{ {
tmp = in[0] + ":\\" + in.substr(2); tmp = in[0] + (":\\" + in.substr(2));
} }
else tmp = in; else tmp = in;
@ -480,11 +480,12 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
// <folder>\Scenes\<hh>\<*>.lws // <folder>\Scenes\<hh>\<*>.lws
// where <hh> is optional. // where <hh> is optional.
std::string test = ".." + io->getOsSeparator() + tmp; std::string test = ".." + (io->getOsSeparator() + tmp);
if (io->Exists(test)) if (io->Exists(test)) {
return test; return test;
}
test = ".." + io->getOsSeparator() + test; test = ".." + (io->getOsSeparator() + test);
if (io->Exists(test)) { if (io->Exists(test)) {
return test; return test;
} }

View File

@ -89,7 +89,7 @@ public:
} }
// https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462 // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
#if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) #if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void LogWarn (const char* message) { static void LogWarn (const char* message) {

View File

@ -1,370 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_M3_IMPORTER
#include "M3Importer.h"
#include <sstream>
namespace Assimp {
namespace M3 {
static const aiImporterDesc desc = {
"StarCraft M3 Importer",
"",
"",
"",
aiImporterFlags_SupportBinaryFlavour,
0,
0,
0,
0,
"m3"
};
// ------------------------------------------------------------------------------------------------
// Constructor.
M3Importer::M3Importer() :
m_pHead( NULL ),
m_pRefs( NULL ),
m_Buffer()
{
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor.
M3Importer::~M3Importer()
{
m_pHead = NULL;
m_pRefs = NULL;
}
// ------------------------------------------------------------------------------------------------
// Check for readable file format.
bool M3Importer::CanRead( const std::string &rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const
{
if ( !checkSig ) {
return SimpleExtensionCheck( rFile, "m3" );
}
return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* M3Importer::GetInfo () const
{
return &desc;
}
// ------------------------------------------------------------------------------------------------
void M3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
{
ai_assert( !pFile.empty() );
const std::string mode = "rb";
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode ) );
if ( NULL == file.get() ) {
throw DeadlyImportError( "Failed to open file " + pFile + ".");
}
// Get the file-size and validate it, throwing an exception when it fails
const size_t filesize = file->FileSize();
if( filesize < 1 ) {
throw DeadlyImportError( "M3-file is too small.");
}
m_Buffer.resize( filesize );
file->Read( &m_Buffer[ 0 ], sizeof( unsigned char ), filesize );
m_pHead = reinterpret_cast<MD33*>( &m_Buffer[ 0 ] );
m_pRefs = reinterpret_cast<ReferenceEntry*>( &m_Buffer[ 0 ] + m_pHead->ofsRefs );
MODL20* pMODL20( NULL );
MODL23* pMODL23( NULL );
VertexExt* pVerts1( NULL );
Vertex* pVerts2( NULL );
DIV *pViews( NULL );
Region* regions( NULL );
uint16* faces( NULL );
uint32 nVertices = 0;
bool ok = true;
switch( m_pRefs[ m_pHead->MODL.ref ].type ) {
case 20:
pMODL20 = GetEntries<MODL20>( m_pHead->MODL );
if ( ( pMODL20->flags & 0x20000) != 0 ) { // Has vertices
if( (pMODL20->flags & 0x40000) != 0 ) { // Has extra 4 byte
pVerts1 = GetEntries<VertexExt>( pMODL20->vertexData );
nVertices = pMODL20->vertexData.nEntries/sizeof(VertexExt);
}
else {
pVerts2 = GetEntries<Vertex>( pMODL20->vertexData );
nVertices = pMODL20->vertexData.nEntries / sizeof( Vertex );
}
}
pViews = GetEntries<DIV>( pMODL20->views );
break;
case 23:
pMODL23 = GetEntries<MODL23>(m_pHead->MODL );
if( (pMODL23->flags & 0x20000) != 0 ) { // Has vertices
if( (pMODL23->flags & 0x40000) != 0 ) { // Has extra 4 byte
pVerts1 = GetEntries<VertexExt>( pMODL23->vertexData );
nVertices = pMODL23->vertexData.nEntries/sizeof( VertexExt );
}
else {
pVerts2 = GetEntries<Vertex>( pMODL23->vertexData );
nVertices = pMODL23->vertexData.nEntries/sizeof( Vertex );
}
}
pViews = GetEntries<DIV>( pMODL23->views );
break;
default:
ok = false;
break;
}
// Everything ok, if not throw an exception
if ( !ok ) {
throw DeadlyImportError( "Failed to open file " + pFile + ".");
}
// Get all region data
regions = GetEntries<Region>( pViews->regions );
// Get the face data
faces = GetEntries<uint16>( pViews->faces );
// Convert the vertices
std::vector<aiVector3D> vertices;
vertices.resize( nVertices );
unsigned int offset = 0;
for ( unsigned int i = 0; i < nVertices; i++ ) {
if ( pVerts1 ) {
vertices[ offset ].Set( pVerts1[ i ].pos.x, pVerts1[ i ].pos.y, pVerts1[ i ].pos.z );
++offset;
}
if ( pVerts2 ) {
vertices[ offset ].Set( pVerts2[ i ].pos.x, pVerts2[ i ].pos.y, pVerts2[ i ].pos.z );
++offset;
}
}
// Write the UV coordinates
offset = 0;
std::vector<aiVector3D> uvCoords;
uvCoords.resize( nVertices );
for( unsigned int i = 0; i < nVertices; ++i ) {
if( pVerts1 ) {
float u = (float) pVerts1[ i ].uv[ 0 ] / 2048;
float v = (float) pVerts1[ i ].uv[ 1 ] / 2048;
uvCoords[ offset ].Set( u, v, 0.0f );
++offset;
}
if( pVerts2 ) {
float u = (float) pVerts2[ i ].uv[ 0 ] / 2048;
float v = (float) pVerts2[ i ].uv[ 1 ] / 2048;
uvCoords[ offset ].Set( u, v, 0.0f );
++offset;
}
}
// Compute the normals
std::vector<aiVector3D> normals;
normals.resize( nVertices );
float w = 0.0f;
Vec3D norm;
offset = 0;
for( unsigned int i = 0; i < nVertices; i++ ) {
w = 0.0f;
if( pVerts1 ) {
norm.x = (float) 2*pVerts1[ i ].normal[ 0 ]/255.0f - 1;
norm.y = (float) 2*pVerts1[ i ].normal[ 1 ]/255.0f - 1;
norm.z = (float) 2*pVerts1[ i ].normal[ 2 ]/255.0f - 1;
w = (float) pVerts1[ i ].normal[ 3 ]/255.0f;
}
if( pVerts2 ) {
norm.x = (float) 2*pVerts2[ i ].normal[ 0 ]/255.0f - 1;
norm.y = (float) 2*pVerts2[ i ].normal[ 1 ]/255.0f - 1;
norm.z = (float) 2*pVerts2[ i ].normal[ 2 ]/255.0f - 1;
w = (float) pVerts2[ i ].normal[ 3 ] / 255.0f;
}
if ( w ) {
const float invW = 1.0f / w;
norm.x = norm.x * invW;
norm.y = norm.y * invW;
norm.z = norm.z * invW;
normals[ offset ].Set( norm.x, norm.y, norm.z );
++offset;
}
}
// Convert the data into the assimp specific data structures
convertToAssimp( pFile, pScene, pViews, regions, faces, vertices, uvCoords, normals );
}
// ------------------------------------------------------------------------------------------------
//
void M3Importer::convertToAssimp( const std::string& pFile, aiScene* pScene, DIV *pViews,
Region *pRegions, uint16 *pFaces,
const std::vector<aiVector3D> &vertices,
const std::vector<aiVector3D> &uvCoords,
const std::vector<aiVector3D> &normals )
{
std::vector<aiMesh*> MeshArray;
// Create the root node
pScene->mRootNode = createNode( NULL );
// Set the name of the scene
pScene->mRootNode->mName.Set( pFile );
aiNode *pRootNode = pScene->mRootNode;
aiNode *pCurrentNode = NULL;
// Lets create the nodes
pRootNode->mNumChildren = pViews->regions.nEntries;
if ( pRootNode->mNumChildren > 0 ) {
pRootNode->mChildren = new aiNode*[ pRootNode->mNumChildren ];
}
for ( unsigned int i=0; i<pRootNode->mNumChildren; ++i ) {
//pRegions[ i ].
// Create a new node
pCurrentNode = createNode( pRootNode );
std::stringstream stream;
stream << "Node_" << i;
pCurrentNode->mName.Set( stream.str().c_str() );
pRootNode->mChildren[ i ] = pCurrentNode;
// Loop over the faces of the nodes
unsigned int numFaces = ( ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ) - pRegions[ i ].ofsIndices ) / 3;
aiMesh *pMesh = new aiMesh;
MeshArray.push_back( pMesh );
pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
pMesh->mNumFaces = numFaces;
pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
aiFace *pCurrentFace = NULL;
unsigned int faceIdx = 0;
for ( unsigned int j = pRegions[ i ].ofsIndices; j < ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ); j += 3 ) {
pCurrentFace = &( pMesh->mFaces[ faceIdx ] );
faceIdx++;
pCurrentFace->mNumIndices = 3;
pCurrentFace->mIndices = new unsigned int[ 3 ];
pCurrentFace->mIndices[ 0 ] = pFaces[ j ];
pCurrentFace->mIndices[ 1 ] = pFaces[ j+1 ];
pCurrentFace->mIndices[ 2 ] = pFaces[ j+2 ];
}
// Now we can create the vertex data itself
pCurrentNode->mNumMeshes = 1;
pCurrentNode->mMeshes = new unsigned int[ 1 ];
const unsigned int meshIdx = MeshArray.size() - 1;
pCurrentNode->mMeshes[ 0 ] = meshIdx;
createVertexData( pMesh, vertices, uvCoords, normals );
}
// Copy the meshes into the scene
pScene->mNumMeshes = MeshArray.size();
pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
unsigned int pos = 0;
for ( std::vector<aiMesh*>::iterator it = MeshArray.begin(); it != MeshArray.end(); ++it ) {
pScene->mMeshes[ pos ] = *it;
++pos;
}
}
// ------------------------------------------------------------------------------------------------
//
void M3Importer::createVertexData( aiMesh *pMesh, const std::vector<aiVector3D> &vertices,
const std::vector<aiVector3D> &uvCoords,
const std::vector<aiVector3D> &normals )
{
pMesh->mNumVertices = pMesh->mNumFaces * 3;
pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
pMesh->mNumUVComponents[ 0 ] = 2;
pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
unsigned int pos = 0;
for ( unsigned int currentFace = 0; currentFace < pMesh->mNumFaces; currentFace++ ) {
aiFace *pFace = &( pMesh->mFaces[ currentFace ] );
for ( unsigned int currentIdx=0; currentIdx<pFace->mNumIndices; currentIdx++ ) {
const unsigned int idx = pFace->mIndices[ currentIdx ];
if ( vertices.size() > idx ) {
pMesh->mVertices[ pos ] = vertices[ idx ];
pMesh->mNormals[ pos ] = normals[ idx ];
pMesh->mTextureCoords[ 0 ]->x = uvCoords[ idx ].x;
pMesh->mTextureCoords[ 0 ]->y = uvCoords[ idx ].y;
pFace->mIndices[ currentIdx ] = pos;
pos++;
}
}
}
}
// ------------------------------------------------------------------------------------------------
//
aiNode *M3Importer::createNode( aiNode *pParent )
{
aiNode *pNode = new aiNode;
if ( pParent )
pNode->mParent = pParent;
else
pNode->mParent = NULL;
return pNode;
}
// ------------------------------------------------------------------------------------------------
} // Namespace M3
} // Namespace Assimp
#endif // ASSIMP_BUILD_NO_M3_IMPORTER

View File

@ -1,726 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef AI_M3LOADER_H_INCLUDED
#define AI_M3LOADER_H_INCLUDED
#include <vector>
namespace Assimp {
namespace M3 {
// ------------------------------------------------------------------------------------------------
// The following data definitions are from http://code.google.com/p/libm3/, many thanks for that
// help.
// ------------------------------------------------------------------------------------------------
typedef unsigned char uint8;
typedef char int8;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned int uint32;
typedef int int32;
class Vec3D
{
public:
float x,y,z;
Vec3D(float x0 = 0.0f, float y0 = 0.0f, float z0 = 0.0f) : x(x0), y(y0), z(z0) {}
Vec3D(const Vec3D& v) : x(v.x), y(v.y), z(v.z) {}
void reset()
{
x = y = z = 0.0f;
}
Vec3D& operator= (const Vec3D &v)
{
x = v.x;
y = v.y;
z = v.z;
return *this;
}
Vec3D operator+ (const Vec3D &v) const
{
Vec3D r(x+v.x,y+v.y,z+v.z);
return r;
}
Vec3D operator- (const Vec3D &v) const
{
Vec3D r(x-v.x,y-v.y,z-v.z);
return r;
}
float operator* (const Vec3D &v) const
{
return x*v.x + y*v.y + z*v.z;
}
Vec3D operator* (float d) const
{
Vec3D r(x*d,y*d,z*d);
return r;
}
Vec3D operator/ (float d) const
{
Vec3D r(x/d,y/d,z/d);
return r;
}
friend Vec3D operator* (float d, const Vec3D& v)
{
return v * d;
}
// Cross Product
Vec3D operator% (const Vec3D &v) const
{
Vec3D r(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
return r;
}
Vec3D& operator+= (const Vec3D &v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
Vec3D& operator-= (const Vec3D &v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
Vec3D& operator*= (float d)
{
x *= d;
y *= d;
z *= d;
return *this;
}
float lengthSquared() const
{
return x*x+y*y+z*z;
}
float length() const
{
return sqrtf(x*x+y*y+z*z);
}
Vec3D& normalize()
{
this->operator*= (1.0f/length());
return *this;
}
Vec3D operator~ () const
{
Vec3D r(*this);
r.normalize();
return r;
}
operator float*()
{
return (float*)this;
}
};
class Vec2D
{
public:
float x,y;
Vec2D(float x0 = 0.0f, float y0 = 0.0f) : x(x0), y(y0) {}
Vec2D(const Vec2D& v) : x(v.x), y(v.y) {}
Vec2D& operator= (const Vec2D &v)
{
x = v.x;
y = v.y;
return *this;
}
Vec2D operator+ (const Vec2D &v) const
{
Vec2D r(x+v.x,y+v.y);
return r;
}
Vec2D operator- (const Vec2D &v) const
{
Vec2D r(x-v.x,y-v.y);
return r;
}
float operator* (const Vec2D &v) const
{
return x*v.x + y*v.y;
}
Vec2D operator* (float d) const
{
Vec2D r(x*d,y*d);
return r;
}
friend Vec2D operator* (float d, const Vec2D& v)
{
return v * d;
}
Vec2D& operator+= (const Vec2D &v)
{
x += v.x;
y += v.y;
return *this;
}
Vec2D& operator-= (const Vec2D &v)
{
x -= v.x;
y -= v.y;
return *this;
}
Vec2D& operator*= (float d)
{
x *= d;
y *= d;
return *this;
}
float lengthSquared() const
{
return x*x+y*y;
}
float length() const
{
return sqrtf(x*x+y*y);
}
Vec2D& normalize()
{
this->operator*= (1.0f/length());
return *this;
}
Vec2D operator~ () const
{
Vec2D r(*this);
r.normalize();
return r;
}
operator float*()
{
return (float*)this;
}
};
inline
void rotate(float x0, float y0, float *x, float *y, float angle)
{
float xa = *x - x0, ya = *y - y0;
*x = xa*cosf(angle) - ya*sinf(angle) + x0;
*y = xa*sinf(angle) + ya*cosf(angle) + y0;
}
struct Reference
{
uint32 nEntries; // Code 0x00
uint32 ref; // Code 0x04
};
struct ReferenceEntry
{
char id[ 4 ]; // Code 0x00
uint32 offset; // Code 0x04
uint32 nEntries; // Code 0x08
uint32 type; // Code 0x0C
};
struct MD33
{
char id[4]; // Code 0x00
uint32 ofsRefs; // Code 0x04
uint32 nRefs; // Code 0x08
Reference MODL; // Code 0x0C
};
enum ModelType
{
Type1 = 20,
Type2 = 23
};
enum VertexFormat
{
Vertex_Standard,
Vertex_Extended
};
struct MODL23
{
Reference name; // Code 0x00
uint32 version; // Code 0x08
Reference sequenceHeader; // Code 0x0C
Reference sequenceData; // Code 0x14
Reference sequenceLookup; // Code 0x1C
uint32 d2; // Code 0x24
uint32 d3; // Code 0x28
uint32 d4; // Code 0x2C
Reference STS; // Code 0x30
Reference bones; // Code 0x38
uint32 d5; // Code 0x40
uint32 flags; // Code 0x44
Reference vertexData; // Code 0x48
Reference views; // Code 0x50
Reference B; // Code 0x58
Vec3D extents[2]; // Code 0x60
float radius; // Code 0x78
uint32 d7; // Code 0x7C
uint32 d8; // Code 0x80
uint32 d9; // Code 0x84
uint32 d10; // Code 0x88
uint32 d11; // Code 0x8C
uint32 d12; // Code 0x90
uint32 d13; // Code 0x94
uint32 d14; // Code 0x98
uint32 d15; // Code 0x9C
uint32 d16; // Code 0xA0
uint32 d17; // Code 0xA4
uint32 d18; // Code 0xA8
uint32 d19; // Code 0xAC
Reference attachments; // Code 0xB0
Reference attachmentLookup; // Code 0xB8
Reference lights; // Code 0xC0
Reference SHBX; // Code 0xC8
Reference cameras; // Code 0xD0
Reference D; // Code 0xD8
Reference materialLookup; // Code 0xE0
Reference materials; // Code 0xE8
Reference DIS; // Code 0xF0
Reference CMP; // Code 0xF8
Reference TER; // Code 0x10
Reference VOL; // Code 0x10
uint32 d21; // Code 0x11
uint32 d22; // Code 0x11
Reference CREP; // Code 0x11
Reference PAR; // Code 0x12
Reference PARC; // Code 0x12
Reference RIB; // Code 0x13
Reference PROJ; // Code 0x13
Reference FOR; // Code 0x14
Reference WRP; // Code 0x14
uint32 d24; // Code 0x15
uint32 d25; // Code 0x15
Reference PHRB; // Code 0x15
uint32 d27; // Code 0x16
uint32 d28; // Code 0x16
uint32 d29; // Code 0x16
uint32 d30; // Code 0x16
uint32 d32; // Code 0x17
uint32 d33; // Code 0x17
Reference IKJT; // Code 0x17
uint32 d35; // Code 0x18
uint32 d36; // Code 0x18
Reference PATU; // Code 0x18
Reference TRGD; // Code 0x19
Reference IREF; // Code 0x19
Reference E; // Code 0x1A
float matrix[4][4]; // Code 0x1A
Vec3D extent[2]; // Code 0x1E
float rad; // Code 0x20
Reference SSGS; // Code 0x20
Reference ATVL; // Code 0x20
uint32 d61; // Code 0x21
Reference F; // uint16, Code6 0x21
Reference G; // uint16, Code 0x21
Reference BBSC; // Code 0x22
Reference TMD; // Code 0x22
uint32 d62; // Code 0x23
uint32 d63; // Code 0x23
uint32 d64; // Code 0x23
};
struct MODL20
{
Reference name; // Code 0x00
uint32 version; // Code 0x08
Reference sequenceHeader; // Code 0x0C
Reference sequenceData; // Code 0x14
Reference sequenceLookup; // Code 0x1C
uint32 d2; // Code 0x24
uint32 d3; // Code 0x28
uint32 d4; // Code 0x2C
Reference STS; // Code 0x30
Reference bones; // Code 0x38
uint32 d5; // Code 0x44
uint32 flags; // Code 0x44
Reference vertexData; // uint8, Code 0x48
Reference views; // Code 0x50
Reference B; // uint16, Code 0x58
Vec3D extents[2]; // Code 0x60
float radius; // Code 0x78
uint32 d7; // Code 0x7C
uint32 d8; // Code 0x80
uint32 d9; // Code 0x84
uint32 d10; // Code 0x88
uint32 d11; // Code 0x8C
uint32 d12; // Code 0x90
uint32 d13; // Code 0x94
uint32 d14; // Code 0x98
uint32 d15; // Code 0x9C
uint32 d16; // Code 0xA0
uint32 d17; // Code 0xA4
uint32 d18; // Code 0xA8
uint32 d19; // Code 0xAC
Reference attachments; // Code 0xB0
Reference attachmentLookup; // uint16, Code 0xB8
Reference lights; // Code 0xC0
Reference cameras; // Code 0xC8
Reference D; // uint16, Code 0xD0
Reference materialLookup; // Code 0xD8
Reference materials; // Code 0xE0
Reference DIS; // Code 0xE8
Reference CMP; // Code 0xF0
Reference TER; // Code 0xF8
uint32 d20; // Code 0x10
uint32 d21; // Code 0x10
uint32 d22; // Code 0x10
uint32 d23; // Code 0x10
Reference CREP; // Code 0x11
Reference PAR; // Code 0x11
Reference PARC; // Code 0x12
Reference RIB; // Code 0x12
Reference PROJ; // Code 0x13
Reference FOR; // Code 0x13
uint32 d25; // Code 0x14
uint32 d26; // Code 0x14
uint32 d27; // Code 0x14
uint32 d28; // Code 0x14
Reference PHRB; // Code 0x15
uint32 d30; // Code 0x15
uint32 d31; // Code 0x15
uint32 d32; // Code 0x16
uint32 d33; // Code 0x16
uint32 d34; // Code 0x16
uint32 d35; // Code 0x16
Reference IKJT; // Code 0x17
uint32 d36; // Code 0x17
uint32 d37; // Code 0x17
Reference PATU; // Code 0x18
Reference TRGD; // Code 0x18
Reference IREF; // Code 0x19
Reference E; // int32, Code 0x19
float matrix[4][4]; // Code 0x1A
Vec3D extent[2]; // Code 0x1E
float rad; // Code 0x1F
Reference SSGS; // Code 0x1F
uint32 d38; // Code 0x20
uint32 d39; // Code 0x20
Reference BBSC; // Code 0x20
uint32 d40; // Code 0x21
uint32 d41; // Code 0x21
uint32 d42; // Code 0x21
uint32 d43; // Code 0x22
uint32 d44; // Code 0x22
};
struct BONE
{
int32 d1; // Keybone?
Reference name;
uint32 flags;
int16 parent;
int16 s1;
float floats[ 34 ];
};
struct VertexExt // 36 byte
{
Vec3D pos;
uint8 boneWeight[ 4 ];
uint8 boneIndex[ 4 ];
uint8 normal[ 4 ]; //normal_x = (float)normal[0]/255.0f...
int16 uv[ 2 ];
uint32 d1;
uint8 tangent[ 4 ];
};
struct Vertex // 32 byte
{
Vec3D pos;
uint8 boneWeight[4];
uint8 boneIndex[4];
uint8 normal[4]; //normal_x = (float)normal[0]/255.0f...
int16 uv[2];
uint8 tangent[4];
};
struct MATM
{
uint32 d1;
uint32 d2; // Index into MAT-table?
};
struct MAT
{
Reference name;
int ukn1[ 8 ];
float x, y; //always 1.0f
Reference layers[13];
int ukn2[15];
};
struct LAYR
{
int unk;
Reference name;
float unk2[85];
};
struct DIV
{
Reference faces; // Code 0x00
Reference regions; // Code 0x08
Reference BAT; // Code 0x10
Reference MSEC; // Code 0x18
};
struct Region
{
uint32 unk;
uint16 ofsVertices;
uint16 nVertices;
uint32 ofsIndices;
uint32 nIndices; // reference into DIV.faces
uint8 unknown[12];
};
struct CAM
{
int32 d1; // Code 0x00
Reference name; // Code 0x04
uint16 flags1; // Code 0x0C
uint16 flags2; // Code 0x0E
};
struct EVNT
{
Reference name; // Code 0x00
int16 unk1[4]; // Code 0x08
float matrix[4][4]; // Code 0x10
int32 unk2[4]; // Code 0x50
};
struct ATT
{
int32 unk; // Code 0x00
Reference name; // Code 0x04
int32 bone; // Code 0x0C
};
struct PHSH
{
float m[ 4 ][ 4 ];
float f1;
float f2;
Reference refs[ 5 ];
float f3;
};
struct SEQS
{
int32 d1; // Code 0x00
int32 d2; // Code 0x04
Reference name; // Code 0x08
int32 d3; // Code 0x10
uint32 length; // Code 0x14
int32 d4; // Code 0x18
uint32 flags; // Code 0x1C
int32 unk[5]; // Code 0x20
Vec3D extents[2]; // Code 0x34
float radius; // Code 0x4C
int32 d5; // Code 0x50
int32 d6; // Code 0x54
};
struct STC
{
Reference name; // Code 0x00
uint16 s1; // Code 0x08
uint16 s2; // Code 0x0A
uint16 s3; // Code 0x0C
uint16 s4; // Code 0x0E
Reference unk2; // uint32 // Code 0x12
Reference unk3; // uint32 // Code 0x1A
uint32 d3; // Code 0x22
Reference evt; // Code 0x24
Reference unk4[11]; // Seems to be transformation data // Code 0x2C
Reference bnds; // Code 0x84
};
struct STS
{
Reference unk1; // uint32 // Code 0x00
int32 unk[3]; // Code 0x08
int16 s1; // Code 0x14
int16 s2; // Code 0x16
};
struct STG
{
Reference name; // Code 0x00
Reference stcID; // Code 0x08
};
struct SD
{
Reference timeline; // Code 0x00
uint32 flags; // Code 0x08
uint32 length; // Code 0x0C
Reference data; // Code 0x10
};
struct BNDS
{
Vec3D extents1[2]; // Code 0x00
float radius1; // Code 0x18
Vec3D extents2[2]; // Code 0x1C
float radius2; // Code 0x34
};
struct VEC2
{
float x, y;
};
struct VEC3
{
float x, y, z;
};
struct VEC4
{
float x, y, z, w;
};
struct QUAT
{
float x, y, z, w;
};
// ------------------------------------------------------------------------------------------------
/** Loader to import M3-models.
*/
// ------------------------------------------------------------------------------------------------
class M3Importer : public BaseImporter
{
friend class Importer;
public:
/// @brief The default constructor.
M3Importer();
/// @brief The destructor.
~M3Importer();
/// @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:
const aiImporterDesc* GetInfo () const;
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
void convertToAssimp( const std::string& pFile, aiScene* pScene, DIV *pViews, Region *pRegions, uint16 *pFaces,
const std::vector<aiVector3D> &vertices, const std::vector<aiVector3D> &uvCoords, const std::vector<aiVector3D> &normals );
void createVertexData( aiMesh *pMesh, const std::vector<aiVector3D> &vertices, const std::vector<aiVector3D> &uvCoords,
const std::vector<aiVector3D> &normals );
aiNode *createNode( aiNode *pParent );
template<typename T>
T* GetEntries( Reference ref );
private:
MD33 *m_pHead;
ReferenceEntry *m_pRefs;
std::vector<unsigned char> m_Buffer;
};
// ------------------------------------------------------------------------------------------------
template<typename T>
inline
T* M3Importer::GetEntries( Reference ref )
{
return (T*) ( &m_Buffer[ 0 ] + m_pRefs[ ref.ref ].offset );
}
// ------------------------------------------------------------------------------------------------
} // Namespace M3
} // Namespace Assimp
#endif // AI_M3LOADER_H_INCLUDED

View File

@ -187,7 +187,6 @@ void MD5Importer::LoadFileIntoMemory (IOStream* file)
ai_assert(fileSize); ai_assert(fileSize);
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
pScene = pScene;
mBuffer = new char[fileSize+1]; mBuffer = new char[fileSize+1];
file->Read( (void*)mBuffer, 1, fileSize); file->Read( (void*)mBuffer, 1, fileSize);
iLineNumber = 1; iLineNumber = 1;

View File

@ -787,7 +787,6 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// What the fuck does this function do? Can't remember
void MDLImporter::ParseSkinLump_3DGS_MDL7( void MDLImporter::ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent, const unsigned char* szCurrent,
const unsigned char** szCurrentOut, const unsigned char** szCurrentOut,

View File

@ -102,7 +102,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
} }
// data is given in floats, simply copy it // data is given in floats, simply copy it
unsigned int iWrite; unsigned int iWrite = 0;
if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) { if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
iWrite = prop->mDataLength / sizeof(float); iWrite = prop->mDataLength / sizeof(float);
if (pMax) { if (pMax) {
@ -175,7 +175,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
} }
// data is given in ints, simply copy it // data is given in ints, simply copy it
unsigned int iWrite; unsigned int iWrite = 0;
if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) { if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) {
iWrite = prop->mDataLength / sizeof(int32_t); iWrite = prop->mDataLength / sizeof(int32_t);
if (pMax) { if (pMax) {

View File

@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "AssimpPCH.h" #include "AssimpPCH.h"
#ifndef AI_BUILD_NO_NDO_IMPORTER #ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
#include "NDOLoader.h" #include "NDOLoader.h"
using namespace Assimp; using namespace Assimp;

View File

@ -59,10 +59,16 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// we're still here - export successfully completed. Write both the main OBJ file and the material script // we're still here - export successfully completed. Write both the main OBJ file and the material script
{ {
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
}
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1); outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
} }
{ {
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt")); boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
}
outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1); outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
} }
} }

1
code/ObjFileData.h 100644 → 100755
View File

@ -283,6 +283,7 @@ struct Model
m_pCurrent(NULL), m_pCurrent(NULL),
m_pCurrentMaterial(NULL), m_pCurrentMaterial(NULL),
m_pDefaultMaterial(NULL), m_pDefaultMaterial(NULL),
m_pGroupFaceIDs(NULL),
m_strActiveGroup(""), m_strActiveGroup(""),
m_pCurrentMesh(NULL) m_pCurrentMesh(NULL)
{ {

View File

@ -528,18 +528,12 @@ int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
// Getter for a group name. // Getter for a group name.
void ObjFileParser::getGroupName() void ObjFileParser::getGroupName()
{ {
// Get next word from data buffer std::string strGroupName;
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) )
return; return;
// Store the group name in the group library
char *pStart = &(*m_DataIt);
while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
m_DataIt++;
std::string strGroupName( pStart, &(*m_DataIt) );
// Change active group, if necessary // Change active group, if necessary
if ( m_pModel->m_strActiveGroup != strGroupName ) if ( m_pModel->m_strActiveGroup != strGroupName )
{ {

View File

@ -165,6 +165,15 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
//____________________________________________________________ //____________________________________________________________
//skip submeshnames (stupid irrxml)
if(MeshFile->getNodeName()==string("submeshnames"))
{
XmlRead(MeshFile.get());
while(MeshFile->getNodeName()==string("submesh"))
XmlRead(MeshFile.get());
}
//----------------Load the skeleton: ------------------------------- //----------------Load the skeleton: -------------------------------
vector<Bone> Bones; vector<Bone> Bones;
vector<Animation> Animations; vector<Animation> Animations;

View File

@ -64,10 +64,7 @@ namespace Ogre
aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
{ {
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene /*For better understanding of the material parser, here is a material example file:
(void)m_CurrentScene;
/*For bettetr understanding of the material parser, here is a material example file:
material Sarg material Sarg
{ {
@ -143,7 +140,7 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
if(NULL==MatFilePtr) if(NULL==MatFilePtr)
{ {
DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!"); DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!");
return NULL; return new aiMaterial();
} }
} }
} }

View File

@ -182,7 +182,7 @@ void OgreImporter::ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsi
XmlRead(Reader); XmlRead(Reader);
/*it might happen, that we have more than one attribute per vertex (they are not splitted to different buffers) /*it might happen, that we have more than one attribute per vertex (they are not splitted to different buffers)
so the break condition is a bit tricky (well, IrrXML just sucks :( )*/ so the break condition is a bit tricky */
while(Reader->getNodeName()==string("vertex") while(Reader->getNodeName()==string("vertex")
||Reader->getNodeName()==string("position") ||Reader->getNodeName()==string("position")
||Reader->getNodeName()==string("normal") ||Reader->getNodeName()==string("normal")

View File

@ -77,8 +77,6 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vecto
if(!SkeletonFile) if(!SkeletonFile)
throw DeadlyImportError(string("Failed to create XML Reader for ")+FileName); throw DeadlyImportError(string("Failed to create XML Reader for ")+FileName);
//Quick note: Whoever read this should know this one thing: irrXml fucking sucks!!!
XmlRead(SkeletonFile); XmlRead(SkeletonFile);
if(string("skeleton")!=SkeletonFile->getNodeName()) if(string("skeleton")!=SkeletonFile->getNodeName())
throw DeadlyImportError("No <skeleton> node in SkeletonFile: "+FileName); throw DeadlyImportError("No <skeleton> node in SkeletonFile: "+FileName);
@ -169,12 +167,12 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vecto
Bones[ChildId].ParentId=ParentId; Bones[ChildId].ParentId=ParentId;
Bones[ParentId].Children.push_back(ChildId); Bones[ParentId].Children.push_back(ChildId);
XmlRead(SkeletonFile);//I once forget this line, which led to an endless loop, did i mentioned, that irrxml sucks?? XmlRead(SkeletonFile);
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
//--------- Calculate the WorldToBoneSpace Matrix recursivly for all bones: ------------------ //--------- Calculate the WorldToBoneSpace Matrix recursively for all bones: ------------------
BOOST_FOREACH(Bone &theBone, Bones) BOOST_FOREACH(Bone &theBone, Bones)
{ {
if(-1==theBone.ParentId) //the bone is a root bone if(-1==theBone.ParentId) //the bone is a root bone

View File

@ -57,6 +57,10 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// we're still here - export successfully completed. Write the file. // we're still here - export successfully completed. Write the file.
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
}
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1); outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
} }

View File

@ -47,6 +47,7 @@ corresponding preprocessor flag to selectively disable steps.
*/ */
#include "AssimpPCH.h" #include "AssimpPCH.h"
#include "ProcessHelper.h"
#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS #ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS
# include "CalcTangentsProcess.h" # include "CalcTangentsProcess.h"
@ -215,7 +216,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS) #if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
out.push_back( new FlipWindingOrderProcess()); out.push_back( new FlipWindingOrderProcess());
#endif #endif
#if (!defined ASSIMP_BUILD_DEBONE_PROCESS) #if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS)
out.push_back( new DeboneProcess()); out.push_back( new DeboneProcess());
#endif #endif
#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS) #if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)

View File

@ -379,8 +379,7 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
light->mColorSpecular = light->mColorDiffuse; light->mColorSpecular = light->mColorDiffuse;
// We don't need the rest, but we need to know where // We don't need the rest, but we need to know where this chunk ends.
// this fucking chunk ends.
unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4()); unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4());
// skip the background file name // skip the background file name

View File

@ -525,7 +525,7 @@ STEP::LazyObject::LazyObject(DB& db, uint64_t id,uint64_t /*line*/, const char*
--skip_depth; --skip_depth;
} }
if (skip_depth == 1 && *a=='#') { if (skip_depth >= 1 && *a=='#') {
const char* tmp; const char* tmp;
const int64_t num = static_cast<int64_t>( strtoul10_64(a+1,&tmp) ); const int64_t num = static_cast<int64_t>( strtoul10_64(a+1,&tmp) );
db.MarkRef(num,id); db.MarkRef(num,id);

View File

@ -57,6 +57,23 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// we're still here - export successfully completed. Write the file. // we're still here - export successfully completed. Write the file.
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
}
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)
{
// invoke the exporter
STLExporter exporter(pFile, pScene, true);
// we're still here - export successfully completed. Write the file.
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
}
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1); outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
} }
@ -64,7 +81,7 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
STLExporter :: STLExporter(const char* _filename, const aiScene* pScene) STLExporter :: STLExporter(const char* _filename, const aiScene* pScene, bool binary)
: filename(_filename) : filename(_filename)
, pScene(pScene) , pScene(pScene)
, endl("\n") , endl("\n")
@ -72,14 +89,31 @@ STLExporter :: STLExporter(const char* _filename, const aiScene* pScene)
// make sure that all formatting happens using the standard, C locale and not the user's current locale // make sure that all formatting happens using the standard, C locale and not the user's current locale
const std::locale& l = std::locale("C"); const std::locale& l = std::locale("C");
mOutput.imbue(l); mOutput.imbue(l);
if (binary) {
char buf[80] = {0} ;
buf[0] = 'A'; buf[1] = 's'; buf[2] = 's'; buf[3] = 'i'; buf[4] = 'm'; buf[5] = 'p';
buf[6] = 'S'; buf[7] = 'c'; buf[8] = 'e'; buf[9] = 'n'; buf[10] = 'e';
mOutput.write(buf, 80);
unsigned int meshnum = 0;
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
for (unsigned int j = 0; j < pScene->mMeshes[i]->mNumFaces; ++j) {
meshnum++;
}
}
AI_SWAP4(meshnum);
mOutput.write((char *)&meshnum, 4);
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
WriteMeshBinary(pScene->mMeshes[i]);
}
} else {
const std::string& name = "AssimpScene";
const std::string& name = "AssimpScene"; mOutput << "solid " << name << endl;
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
mOutput << "solid " << name << endl; WriteMesh(pScene->mMeshes[i]);
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { }
WriteMesh(pScene->mMeshes[i]); mOutput << "endsolid " << name << endl;
} }
mOutput << "endsolid " << name << endl;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -109,4 +143,31 @@ void STLExporter :: WriteMesh(const aiMesh* m)
} }
} }
void STLExporter :: WriteMeshBinary(const aiMesh* m)
{
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
const aiFace& f = m->mFaces[i];
// we need per-face normals. We specified aiProcess_GenNormals as pre-requisite for this exporter,
// but nonetheless we have to expect per-vertex normals.
aiVector3D nor;
if (m->mNormals) {
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
nor += m->mNormals[f.mIndices[a]];
}
nor.Normalize();
}
float nx = nor.x, ny = nor.y, nz = nor.z;
AI_SWAP4(nx); AI_SWAP4(ny); AI_SWAP4(nz);
mOutput.write((char *)&nx, 4); mOutput.write((char *)&ny, 4); mOutput.write((char *)&nz, 4);
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
const aiVector3D& v = m->mVertices[f.mIndices[a]];
float vx = v.x, vy = v.y, vz = v.z;
AI_SWAP4(vx); AI_SWAP4(vy); AI_SWAP4(vz);
mOutput.write((char *)&vx, 4); mOutput.write((char *)&vy, 4); mOutput.write((char *)&vz, 4);
}
char dummy[2] = {0};
mOutput.write(dummy, 2);
}
}
#endif #endif

View File

@ -59,7 +59,7 @@ class STLExporter
{ {
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
STLExporter(const char* filename, const aiScene* pScene); STLExporter(const char* filename, const aiScene* pScene, bool binary = false);
public: public:
@ -69,6 +69,7 @@ public:
private: private:
void WriteMesh(const aiMesh* m); void WriteMesh(const aiMesh* m);
void WriteMeshBinary(const aiMesh* m);
private: private:

View File

@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
namespace {
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"Stereolithography (STL) Importer", "Stereolithography (STL) Importer",
"", "",
@ -64,6 +65,34 @@ static const aiImporterDesc desc = {
"stl" "stl"
}; };
// A valid binary STL buffer should consist of the following elements, in order:
// 1) 80 byte header
// 2) 4 byte face count
// 3) 50 bytes per face
bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
if (fileSize < 84)
return false;
const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
return expectedBinaryFileSize == fileSize;
}
// An ascii STL buffer will begin with "solid NAME", where NAME is optional.
// Note: The "solid NAME" check is necessary, but not sufficient, to determine
// if the buffer is ASCII; a binary header could also begin with "solid NAME".
bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
if (IsBinarySTL(buffer, fileSize))
return false;
if (fileSize < 5)
return false;
return strncmp(buffer, "solid", 5) == 0;
}
} // namespace
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
STLImporter::STLImporter() STLImporter::STLImporter()
@ -136,12 +165,13 @@ void STLImporter::InternReadFile( const std::string& pFile,
bool bMatClr = false; bool bMatClr = false;
// check whether the file starts with 'solid' - if (IsBinarySTL(mBuffer, fileSize)) {
// in this case we can simply assume it IS a text file. finished. bMatClr = LoadBinaryFile();
if (!::strncmp(mBuffer,"solid",5)) { } else if (IsAsciiSTL(mBuffer, fileSize)) {
LoadASCIIFile(); LoadASCIIFile();
} else {
throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
} }
else bMatClr = LoadBinaryFile();
// now copy faces // now copy faces
pMesh->mFaces = new aiFace[pMesh->mNumFaces]; pMesh->mFaces = new aiFace[pMesh->mNumFaces];
@ -384,7 +414,7 @@ bool STLImporter::LoadBinaryFile()
} }
aiColor4D* clr = &pMesh->mColors[0][i*3]; aiColor4D* clr = &pMesh->mColors[0][i*3];
clr->a = 1.0f; clr->a = 1.0f;
if (bIsMaterialise) // fuck, this is reversed if (bIsMaterialise) // this is reversed
{ {
clr->r = (color & 0x31u) / 31.0f; clr->r = (color & 0x31u) / 31.0f;
clr->g = ((color & (0x31u<<5))>>5u) / 31.0f; clr->g = ((color & (0x31u<<5))>>5u) / 31.0f;

View File

@ -193,7 +193,7 @@ public:
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
/** Increase the file pointer (relative seeking) */ /** Increase the file pointer (relative seeking) */
void IncPtr(int plus) { void IncPtr(size_t plus) {
current += plus; current += plus;
if (current > limit) { if (current > limit) {
throw DeadlyImportError("End of file or read limit was reached"); throw DeadlyImportError("End of file or read limit was reached");

View File

@ -90,6 +90,19 @@ public:
underlying << sin; underlying << sin;
} }
// The problem described here:
// https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
// can also cause trouble here. Apparently, older gcc versions sometimes copy temporaries
// being bound to const ref& function parameters. Copying streams is not permitted, though.
// This workaround avoids this by manually specifying a copy ctor.
#if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
basic_formatter(const basic_formatter& other) {
underlying << (string)other;
}
#endif
public: public:
operator string () const { operator string () const {

View File

@ -82,7 +82,7 @@ protected:
/** Report a validation error. This will throw an exception, /** Report a validation error. This will throw an exception,
* control won't return. * control won't return.
* @param msg Format string for sprintf().*/ * @param msg Format string for sprintf().*/
AI_WONT_RETURN void ReportError(const char* msg,...); AI_WONT_RETURN void ReportError(const char* msg,...) AI_WONT_RETURN_SUFFIX;
// ------------------------------------------------------------------- // -------------------------------------------------------------------

View File

@ -77,8 +77,11 @@ struct free_it
void* free; void* free;
}; };
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
template<> const std::string LogFunctions<XGLImporter>::log_prefix = "XGL: "; template<> const std::string LogFunctions<XGLImporter>::log_prefix = "XGL: ";
}
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"XGL Importer", "XGL Importer",
"", "",

View File

@ -16,6 +16,7 @@
#define __FAST_A_TO_F_H_INCLUDED__ #define __FAST_A_TO_F_H_INCLUDED__
#include <math.h> #include <math.h>
#include <limits.h>
namespace Assimp namespace Assimp
{ {

View File

@ -164,6 +164,8 @@ int Triangle::Index(const Point* p)
return 2; return 2;
} }
assert(0); assert(0);
return 0;
} }
int Triangle::EdgeIndex(const Point* p1, const Point* p2) int Triangle::EdgeIndex(const Point* p1, const Point* p2)
@ -223,6 +225,8 @@ Point* Triangle::PointCW(Point& point)
return points_[1]; return points_[1];
} }
assert(0); assert(0);
return 0;
} }
// The point counter-clockwise to given point // The point counter-clockwise to given point
@ -236,6 +240,8 @@ Point* Triangle::PointCCW(Point& point)
return points_[0]; return points_[0];
} }
assert(0); assert(0);
return 0;
} }
// The neighbor clockwise to given point // The neighbor clockwise to given point

View File

@ -38,6 +38,7 @@
#include <stdexcept> #include <stdexcept>
#include <assert.h> #include <assert.h>
#include <cmath> #include <cmath>
#include <string>
namespace p2t { namespace p2t {
@ -137,8 +138,8 @@ struct Edge {
p = &p2; p = &p2;
} else if (p1.x == p2.x) { } else if (p1.x == p2.x) {
// Repeat points // Repeat points
// ASSIMP_CHANGE (aramis_acg) // ASSIMP_CHANGE (aramis_acg)
throw std::runtime_error("repeat points"); throw std::runtime_error(std::string("repeat points"));
//assert(false); //assert(false);
} }
} }

View File

@ -1421,6 +1421,10 @@ IFC support is new and considered experimental. Please report any bugs you may e
- The implementation knows only about IFC2X3 and applies this rule set to all models it encounters, - The implementation knows only about IFC2X3 and applies this rule set to all models it encounters,
regardless of their actual version. Loading of older or newer files may fail with parsing errors. regardless of their actual version. Loading of older or newer files may fail with parsing errors.
@subsection ifc_metadata Metadata
IFC file properties (IfcPropertySet) are kept as per-node metadata, see aiNode::mMetaData.
<hr> <hr>
@section ogre Ogre @section ogre Ogre
*ATTENTION*: The Ogre-Loader is currently under development, many things have changed after this documentation was written, but they are not final enough to rewrite the documentation. So things may have changed by now! *ATTENTION*: The Ogre-Loader is currently under development, many things have changed after this documentation was written, but they are not final enough to rewrite the documentation. So things may have changed by now!

View File

@ -25,7 +25,7 @@
# pragma pack(push,1) # pragma pack(push,1)
# define PACK_STRUCT # define PACK_STRUCT
#elif defined( __GNUC__ ) #elif defined( __GNUC__ )
# define PACK_STRUCT __attribute__((packed)) # define PACK_STRUCT __attribute__((gcc_struct, __packed__))
#else #else
# error Compiler not supported # error Compiler not supported
#endif #endif

View File

@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
class ExporterPimpl; class ExporterPimpl;
class IOSystem;
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

View File

@ -409,11 +409,12 @@ public:
* instance. Use GetOrphanedScene() to take ownership of it. * instance. Use GetOrphanedScene() to take ownership of it.
* *
* @note This is a straightforward way to decode models from memory * @note This is a straightforward way to decode models from memory
* buffers, but it doesn't handle model formats spreading their * buffers, but it doesn't handle model formats that spread their
* data across multiple files or even directories. Examples include * data across multiple files or even directories. Examples include
* OBJ or MD3, which outsource parts of their material stuff into * OBJ or MD3, which outsource parts of their material info into
* external scripts. If you need the full functionality, provide * external scripts. If you need full functionality, provide
* a custom IOSystem to make Assimp find these files. * a custom IOSystem to make Assimp find these files and use
* the regular ReadFile() API.
*/ */
const aiScene* ReadFileFromMemory( const aiScene* ReadFileFromMemory(
const void* pBuffer, const void* pBuffer,

View File

@ -208,7 +208,7 @@ enum aiAnimBehaviour
/** This value is not used, it is just here to force the /** This value is not used, it is just here to force the
* the compiler to map this enum to a 32 Bit integer */ * the compiler to map this enum to a 32 Bit integer */
#ifndef SWIG #ifndef SWIG
_aiAnimBehaviour_Force32Bit = 0x8fffffff _aiAnimBehaviour_Force32Bit = INT_MAX
#endif #endif
}; };

View File

@ -170,11 +170,13 @@ ASSIMP_API const C_STRUCT aiScene* aiImportFileExWithProperties(
* Check the return value, and you'll know ... * Check the return value, and you'll know ...
* @return A pointer to the imported data, NULL if the import failed. * @return A pointer to the imported data, NULL if the import failed.
* *
* @note This is a straightforward way to decode models from memory buffers, but it * @note This is a straightforward way to decode models from memory
* doesn't handle model formats spreading their data across multiple files or even * buffers, but it doesn't handle model formats that spread their
* directories. Examples include OBJ or MD3, which outsource parts of their material * data across multiple files or even directories. Examples include
* stuff into external scripts. If you need the full functionality, provide a custom * OBJ or MD3, which outsource parts of their material info into
* IOSystem to make Assimp find these files. * external scripts. If you need full functionality, provide
* a custom IOSystem to make Assimp find these files and use
* the regular aiImportFileEx()/aiImportFileExWithProperties() API.
*/ */
ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemory( ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemory(
const char* pBuffer, const char* pBuffer,

View File

@ -403,7 +403,7 @@ enum aiComponent
* use the #aiProcess_OptimizeGraph step to do this */ * use the #aiProcess_OptimizeGraph step to do this */
aiComponent_LIGHTS = 0x100, aiComponent_LIGHTS = 0x100,
/** Removes all light sources (aiScene::mCameras). /** Removes all cameras (aiScene::mCameras).
* The corresponding scenegraph nodes are NOT removed. * The corresponding scenegraph nodes are NOT removed.
* use the #aiProcess_OptimizeGraph step to do this */ * use the #aiProcess_OptimizeGraph step to do this */
aiComponent_CAMERAS = 0x200, aiComponent_CAMERAS = 0x200,
@ -841,4 +841,6 @@ enum aiComponent
*/ */
#define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION" #define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION"
#define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
#endif // !! AI_CONFIG_H_INC #endif // !! AI_CONFIG_H_INC

View File

@ -60,9 +60,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Other (mixed) configuration switches are listed here: * Other (mixed) configuration switches are listed here:
* ASSIMP_BUILD_NO_COMPRESSED_X * ASSIMP_BUILD_NO_COMPRESSED_X
* - Disable support for compressed X files * - Disable support for compressed X files (zip)
* ASSIMP_BUILD_NO_COMPRESSED_BLEND * ASSIMP_BUILD_NO_COMPRESSED_BLEND
* - Disable support for compressed Blender files*/ * - Disable support for compressed Blender files (zip)
* ASSIMP_BUILD_NO_COMPRESSED_IFC
* - Disable support for IFCZIP files (unzip)
*/
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifndef ASSIMP_BUILD_NO_COMPRESSED_X #ifndef ASSIMP_BUILD_NO_COMPRESSED_X
@ -71,6 +74,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
# define ASSIMP_BUILD_NEED_Z_INFLATE # define ASSIMP_BUILD_NEED_Z_INFLATE
#endif
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
# define ASSIMP_BUILD_NEED_Z_INFLATE
# define ASSIMP_BUILD_NEED_UNZIP
#endif
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
# define ASSIMP_BUILD_NEED_Z_INFLATE
# define ASSIMP_BUILD_NEED_UNZIP
#endif #endif
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -149,6 +162,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# define AI_FORCE_INLINE inline # define AI_FORCE_INLINE inline
#endif // (defined _MSC_VER) #endif // (defined _MSC_VER)
#ifdef __clang__
# define AI_WONT_RETURN_SUFFIX __attribute__((analyzer_noreturn))
#else
# define AI_WONT_RETURN_SUFFIX
#endif // (defined __clang__)
#ifdef __cplusplus #ifdef __cplusplus
/* No explicit 'struct' and 'enum' tags for C++, this keeps showing up /* No explicit 'struct' and 'enum' tags for C++, this keeps showing up
* in doxydocs. * in doxydocs.

View File

@ -80,7 +80,7 @@ enum aiLightSourceType
* compiler to map this enum to a 32 Bit integer. * compiler to map this enum to a 32 Bit integer.
*/ */
#ifndef SWIG #ifndef SWIG
_aiLightSource_Force32Bit = 0x9fffffff _aiLightSource_Force32Bit = INT_MAX
#endif #endif
}; };

View File

@ -100,7 +100,7 @@ enum aiTextureOp
* 32 Bit integers to represent this enum. * 32 Bit integers to represent this enum.
*/ */
#ifndef SWIG #ifndef SWIG
_aiTextureOp_Force32Bit = 0x9fffffff _aiTextureOp_Force32Bit = INT_MAX
#endif #endif
//! @endcond //! @endcond
}; };
@ -136,7 +136,7 @@ enum aiTextureMapMode
* 32 Bit integers to represent this enum. * 32 Bit integers to represent this enum.
*/ */
#ifndef SWIG #ifndef SWIG
_aiTextureMapMode_Force32Bit = 0x9fffffff _aiTextureMapMode_Force32Bit = INT_MAX
#endif #endif
//! @endcond //! @endcond
}; };
@ -181,7 +181,7 @@ enum aiTextureMapping
* 32 Bit integers to represent this enum. * 32 Bit integers to represent this enum.
*/ */
#ifndef SWIG #ifndef SWIG
_aiTextureMapping_Force32Bit = 0x9fffffff _aiTextureMapping_Force32Bit = INT_MAX
#endif #endif
//! @endcond //! @endcond
}; };
@ -301,7 +301,7 @@ enum aiTextureType
* 32 Bit integers to represent this enum. * 32 Bit integers to represent this enum.
*/ */
#ifndef SWIG #ifndef SWIG
_aiTextureType_Force32Bit = 0x9fffffff _aiTextureType_Force32Bit = INT_MAX
#endif #endif
//! @endcond //! @endcond
}; };
@ -379,7 +379,7 @@ enum aiShadingMode
* 32 Bit integers to represent this enum. * 32 Bit integers to represent this enum.
*/ */
#ifndef SWIG #ifndef SWIG
_aiShadingMode_Force32Bit = 0x9fffffff _aiShadingMode_Force32Bit = INT_MAX
#endif #endif
//! @endcond //! @endcond
}; };
@ -425,7 +425,7 @@ enum aiTextureFlags
* 32 Bit integers to represent this enum. * 32 Bit integers to represent this enum.
*/ */
#ifndef SWIG #ifndef SWIG
_aiTextureFlags_Force32Bit = 0x9fffffff _aiTextureFlags_Force32Bit = INT_MAX
#endif #endif
//! @endcond //! @endcond
}; };
@ -474,7 +474,7 @@ enum aiBlendMode
* 32 Bit integers to represent this enum. * 32 Bit integers to represent this enum.
*/ */
#ifndef SWIG #ifndef SWIG
_aiBlendMode_Force32Bit = 0x9fffffff _aiBlendMode_Force32Bit = INT_MAX
#endif #endif
//! @endcond //! @endcond
}; };
@ -568,7 +568,7 @@ enum aiPropertyTypeInfo
* compiler to map this enum to a 32 Bit integer. * compiler to map this enum to a 32 Bit integer.
*/ */
#ifndef SWIG #ifndef SWIG
_aiPTI_Force32Bit = 0x9fffffff _aiPTI_Force32Bit = INT_MAX
#endif #endif
}; };
@ -631,9 +631,13 @@ struct aiMaterialProperty
#ifdef __cplusplus #ifdef __cplusplus
aiMaterialProperty() { aiMaterialProperty()
mData = NULL; : mSemantic( 0 )
mIndex = mSemantic = 0; , mIndex( 0 )
, mDataLength( 0 )
, mType( aiPTI_Float )
, mData( NULL )
{
} }
~aiMaterialProperty() { ~aiMaterialProperty() {
@ -657,7 +661,11 @@ struct aiMaterialProperty
* have to stick with the aiMaterialGetXXX family of unbound functions. * have to stick with the aiMaterialGetXXX family of unbound functions.
* The library defines a set of standard keys (AI_MATKEY_XXX). * The library defines a set of standard keys (AI_MATKEY_XXX).
*/ */
#ifdef __cplusplus
struct ASSIMP_API aiMaterial struct ASSIMP_API aiMaterial
#else
struct aiMaterial
#endif
{ {
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -176,8 +176,6 @@ inline aiReturn aiMaterial::Get<aiString>(const char* pKey,unsigned int type,
} }
#ifndef ASSIMP_BUILD_NO_EXPORT
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template<class TYPE> template<class TYPE>
aiReturn aiMaterial::AddProperty (const TYPE* pInput, aiReturn aiMaterial::AddProperty (const TYPE* pInput,
@ -269,8 +267,6 @@ inline aiReturn aiMaterial::AddProperty<int> (const int* pInput,
pKey,type,index,aiPTI_Integer); pKey,type,index,aiPTI_Integer);
} }
#endif
//! @endcond //! @endcond
#endif //! AI_MATERIAL_INL_INC #endif //! AI_MATERIAL_INL_INC

View File

@ -135,8 +135,9 @@ struct aiFace
//! Default constructor //! Default constructor
aiFace() aiFace()
: mNumIndices( 0 )
, mIndices( NULL )
{ {
mNumIndices = 0; mIndices = NULL;
} }
//! Default destructor. Delete the index array //! Default destructor. Delete the index array
@ -147,21 +148,26 @@ struct aiFace
//! Copy constructor. Copy the index array //! Copy constructor. Copy the index array
aiFace( const aiFace& o) aiFace( const aiFace& o)
: mIndices( NULL )
{ {
mIndices = NULL;
*this = o; *this = o;
} }
//! Assignment operator. Copy the index array //! Assignment operator. Copy the index array
const aiFace& operator = ( const aiFace& o) aiFace& operator = ( const aiFace& o)
{ {
if (&o == this) if (&o == this)
return *this; return *this;
delete[] mIndices; delete[] mIndices;
mNumIndices = o.mNumIndices; mNumIndices = o.mNumIndices;
mIndices = new unsigned int[mNumIndices]; if (mNumIndices) {
::memcpy( mIndices, o.mIndices, mNumIndices * sizeof( unsigned int)); mIndices = new unsigned int[mNumIndices];
::memcpy( mIndices, o.mIndices, mNumIndices * sizeof( unsigned int));
}
else {
mIndices = NULL;
}
return *this; return *this;
} }
@ -243,17 +249,17 @@ struct aiBone
//! Default constructor //! Default constructor
aiBone() aiBone()
: mNumWeights( 0 )
, mWeights( NULL )
{ {
mNumWeights = 0; mWeights = NULL;
} }
//! Copy constructor //! Copy constructor
aiBone(const aiBone& other) aiBone(const aiBone& other)
: mName( other.mName )
, mNumWeights( other.mNumWeights )
, mOffsetMatrix( other.mOffsetMatrix )
{ {
mNumWeights = other.mNumWeights;
mOffsetMatrix = other.mOffsetMatrix;
mName = other.mName;
if (other.mWeights && other.mNumWeights) if (other.mWeights && other.mNumWeights)
{ {
mWeights = new aiVertexWeight[mNumWeights]; mWeights = new aiVertexWeight[mNumWeights];
@ -314,7 +320,7 @@ enum aiPrimitiveType
* compiler to map this enum to a 32 Bit integer. * compiler to map this enum to a 32 Bit integer.
*/ */
#ifndef SWIG #ifndef SWIG
_aiPrimitiveType_Force32Bit = 0x9fffffff _aiPrimitiveType_Force32Bit = INT_MAX
#endif #endif
}; //! enum aiPrimitiveType }; //! enum aiPrimitiveType
@ -373,10 +379,11 @@ struct aiAnimMesh
#ifdef __cplusplus #ifdef __cplusplus
aiAnimMesh() aiAnimMesh()
: mVertices() : mVertices( NULL )
, mNormals() , mNormals( NULL )
, mTangents() , mTangents( NULL )
, mBitangents() , mBitangents( NULL )
, mNumVertices( 0 )
{ {
// fixme consider moving this to the ctor initializer list as well // fixme consider moving this to the ctor initializer list as well
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){
@ -604,29 +611,28 @@ struct aiMesh
//! Default constructor. Initializes all members to 0 //! Default constructor. Initializes all members to 0
aiMesh() aiMesh()
: mPrimitiveTypes( 0 )
, mNumVertices( 0 )
, mNumFaces( 0 )
, mVertices( NULL )
, mNormals( NULL )
, mTangents( NULL )
, mBitangents( NULL )
, mFaces( NULL )
, mNumBones( 0 )
, mBones( 0 )
, mMaterialIndex( 0 )
, mNumAnimMeshes( 0 )
, mAnimMeshes( NULL )
{ {
mNumVertices = 0;
mNumFaces = 0;
mNumAnimMeshes = 0;
mPrimitiveTypes = 0;
mVertices = NULL; mFaces = NULL;
mNormals = NULL; mTangents = NULL;
mBitangents = NULL;
mAnimMeshes = NULL;
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
{ {
mNumUVComponents[a] = 0; mNumUVComponents[a] = 0;
mTextureCoords[a] = NULL; mTextureCoords[a] = NULL;
} }
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
mColors[a] = NULL; mColors[a] = NULL;
mNumBones = 0; mBones = NULL;
mMaterialIndex = 0;
mNumAnimMeshes = 0;
mAnimMeshes = NULL;
} }
//! Deletes all storage allocated for the mesh //! Deletes all storage allocated for the mesh

View File

@ -0,0 +1,120 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file metadata.h
* @brief Defines the data structures for holding node meta information.
*/
#ifndef __AI_METADATA_H_INC__
#define __AI_METADATA_H_INC__
#ifdef __cplusplus
extern "C" {
#endif
// -------------------------------------------------------------------------------
/**
* Container for holding metadata.
*
* Metadata is a key-value store using string keys and values.
*/
// -------------------------------------------------------------------------------
struct aiMetadata
{
/** Length of the mKeys and mValues arrays, respectively */
unsigned int mNumProperties;
/** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
C_STRUCT aiString** mKeys;
/** Arrays of values, may not be NULL. Entries in this array may be NULL if the
* corresponding property key has no assigned value. */
C_STRUCT aiString** mValues;
#ifdef __cplusplus
/** Constructor */
aiMetadata()
{
// set all members to zero by default
mKeys = NULL;
mValues = NULL;
mNumProperties = 0;
}
/** Destructor */
~aiMetadata()
{
if (mKeys && mValues) {
for (unsigned i=0; i<mNumProperties; ++i) {
if (mKeys[i]) {
delete mKeys[i];
}
if (mValues[i]) {
delete mValues[i];
}
}
delete [] mKeys;
delete [] mValues;
}
}
inline bool Get(const aiString& key, aiString& value)
{
for (unsigned i=0; i<mNumProperties; ++i) {
if (mKeys[i] && *mKeys[i]==key) {
value=*mValues[i];
return true;
}
}
return false;
}
#endif // __cplusplus
};
#ifdef __cplusplus
} //extern "C" {
#endif
#endif // __AI_METADATA_H_INC__

View File

@ -52,11 +52,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "camera.h" #include "camera.h"
#include "material.h" #include "material.h"
#include "anim.h" #include "anim.h"
#include "metadata.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** A node in the imported hierarchy. /** A node in the imported hierarchy.
* *
@ -71,16 +73,24 @@ struct aiNode
/** The name of the node. /** The name of the node.
* *
* The name might be empty (length of zero) but all nodes which * The name might be empty (length of zero) but all nodes which
* need to be accessed afterwards by bones or anims are usually named. * need to be referenced by either bones or animations are named.
* Multiple nodes may have the same name, but nodes which are accessed * Multiple nodes may have the same name, except for nodes which are referenced
* by bones (see #aiBone and #aiMesh::mBones) *must* be unique. * by bones (see #aiBone and #aiMesh::mBones). Their names *must* be unique.
* *
* Cameras and lights are assigned to a specific node name - if there * Cameras and lights reference a specific node by name - if there
* are multiple nodes with this name, they're assigned to each of them. * are multiple nodes with this name, they are assigned to each of them.
* <br> * <br>
* There are no limitations regarding the characters contained in * There are no limitations with regard to the characters contained in
* this text. You should be able to handle stuff like whitespace, tabs, * the name string as it is usually taken directly from the source file.
* linefeeds, quotation marks, ampersands, ... . *
* Implementations should be able to handle tokens such as whitespace, tabs,
* line feeds, quotation marks, ampersands etc.
*
* Sometimes assimp introduces new nodes not present in the source file
* into the hierarchy (usually out of necessity because sometimes the
* source hierarchy format is simply not compatible). Their names are
* surrounded by @verbatim <> @endverbatim e.g.
* @verbatim<DummyRootNode> @endverbatim.
*/ */
C_STRUCT aiString mName; C_STRUCT aiString mName;
@ -102,24 +112,39 @@ struct aiNode
/** The meshes of this node. Each entry is an index into the mesh */ /** The meshes of this node. Each entry is an index into the mesh */
unsigned int* mMeshes; unsigned int* mMeshes;
/** Metadata associated with this node or NULL if there is no metadata.
* Whether any metadata is generated depends on the source file format. See the
* @link importer_notes @endlink page for more information on every source file
* format. Importers that don't document any metadata don't write any.
*/
C_STRUCT aiMetadata* mMetaData;
#ifdef __cplusplus #ifdef __cplusplus
/** Constructor */ /** Constructor */
aiNode() aiNode()
{
// set all members to zero by default // set all members to zero by default
mParent = NULL; : mName()
mNumChildren = 0; mChildren = NULL; , mParent()
mNumMeshes = 0; mMeshes = NULL; , mNumChildren()
, mChildren()
, mNumMeshes()
, mMeshes()
, mMetaData()
{
} }
/** Construction from a specific name */ /** Construction from a specific name */
aiNode(const std::string& name) aiNode(const std::string& name)
{
// set all members to zero by default // set all members to zero by default
mParent = NULL; : mName(name)
mNumChildren = 0; mChildren = NULL; , mParent()
mNumMeshes = 0; mMeshes = NULL; , mNumChildren()
mName = name; , mChildren()
, mNumMeshes()
, mMeshes()
, mMetaData()
{
} }
/** Destructor */ /** Destructor */
@ -134,8 +159,10 @@ struct aiNode
} }
delete [] mChildren; delete [] mChildren;
delete [] mMeshes; delete [] mMeshes;
delete mMetaData;
} }
/** Searches for a node with a specific name, beginning at this /** Searches for a node with a specific name, beginning at this
* nodes. Normally you will call this method on the root node * nodes. Normally you will call this method on the root node
* of the scene. * of the scene.
@ -143,22 +170,45 @@ struct aiNode
* @param name Name to search for * @param name Name to search for
* @return NULL or a valid Node if the search was successful. * @return NULL or a valid Node if the search was successful.
*/ */
inline const aiNode* FindNode(const aiString& name) const
{
return FindNode(name.data);
}
inline aiNode* FindNode(const aiString& name) inline aiNode* FindNode(const aiString& name)
{ {
return FindNode(name.data); return FindNode(name.data);
} }
/** @override /** @override
*/ */
inline const aiNode* FindNode(const char* name) const
{
if (!::strcmp( mName.data,name))return this;
for (unsigned int i = 0; i < mNumChildren;++i)
{
const aiNode* const p = mChildren[i]->FindNode(name);
if (p) {
return p;
}
}
// there is definitely no sub-node with this name
return NULL;
}
inline aiNode* FindNode(const char* name) inline aiNode* FindNode(const char* name)
{ {
if (!::strcmp( mName.data,name))return this; if (!::strcmp( mName.data,name))return this;
for (unsigned int i = 0; i < mNumChildren;++i) for (unsigned int i = 0; i < mNumChildren;++i)
{ {
aiNode* p = mChildren[i]->FindNode(name); aiNode* const p = mChildren[i]->FindNode(name);
if (p)return p; if (p) {
return p;
}
} }
// there is definitely no sub node with this name // there is definitely no sub-node with this name
return NULL; return NULL;
} }

View File

@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory.h> #include <memory.h>
#include <math.h> #include <math.h>
#include <stddef.h> #include <stddef.h>
#include <limits.h>
// Our compile configuration // Our compile configuration
#include "defs.h" #include "defs.h"

View File

@ -25,7 +25,7 @@ substituted by assertions ...):
```python ```python
from pyassimp.core import * from pyassimp import *
scene = load('hello.3ds') scene = load('hello.3ds')
assert len(scene.meshes) assert len(scene.meshes)
@ -44,7 +44,7 @@ scene:
```python ```python
from pyassimp.core import * from pyassimp import *
scene = load('hello.3ds') scene = load('hello.3ds')
for c in scene.rootnode.children: for c in scene.rootnode.children:

View File

@ -0,0 +1 @@
from .core import *

View File

@ -58,14 +58,14 @@ def make_tuple(ai_obj, type = None):
return res return res
def call_init(obj, caller = None): def call_init(obj, caller = None):
# init children # init children
if hasattr(obj, '_init'): if helper.hasattr_silent(obj, '_init'):
obj._init(parent = caller) obj._init(parent = caller)
# pointers # pointers
elif hasattr(obj, 'contents'): elif helper.hasattr_silent(obj, 'contents'):
if hasattr(obj.contents, '_init'): if helper.hasattr_silent(obj.contents, '_init'):
obj.contents._init(target = obj, parent = caller) obj.contents._init(target = obj, parent = caller)
@ -76,7 +76,7 @@ def _init(self, target = None, parent = None):
:param target: set the object which receive the added methods. Useful when manipulating :param target: set the object which receive the added methods. Useful when manipulating
pointers, to skip the intermediate 'contents' deferencing. pointers, to skip the intermediate 'contents' deferencing.
""" """
if hasattr(self, '_is_init'): if helper.hasattr_silent(self, '_is_init'):
return self return self
self._is_init = True self._is_init = True
@ -108,7 +108,7 @@ def _init(self, target = None, parent = None):
if isinstance(obj, structs.String): if isinstance(obj, structs.String):
setattr(target, 'name', str(obj.data)) setattr(target, 'name', obj.data.decode("utf-8"))
setattr(target.__class__, '__repr__', lambda x: str(x.__class__) + "(" + x.name + ")") setattr(target.__class__, '__repr__', lambda x: str(x.__class__) + "(" + x.name + ")")
setattr(target.__class__, '__str__', lambda x: x.name) setattr(target.__class__, '__str__', lambda x: x.name)
continue continue
@ -121,7 +121,7 @@ def _init(self, target = None, parent = None):
logger.debug("Added a parent as self." + name) logger.debug("Added a parent as self." + name)
continue continue
if hasattr(self, 'mNum' + m[1:]): if helper.hasattr_silent(self, 'mNum' + m[1:]):
length = getattr(self, 'mNum' + m[1:]) length = getattr(self, 'mNum' + m[1:])
@ -313,7 +313,7 @@ def _finalize_mesh(mesh, target):
data = numpy.array([make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)], dtype=numpy.float32) data = numpy.array([make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)], dtype=numpy.float32)
setattr(target, name[1:].lower(), data) setattr(target, name[1:].lower(), data)
else: else:
setattr(target, name[1:].lower(), []) setattr(target, name[1:].lower(), numpy.array([], dtype="float32"))
def fillarray(name): def fillarray(name):
mAttr = getattr(mesh, name) mAttr = getattr(mesh, name)
@ -336,6 +336,27 @@ def _finalize_mesh(mesh, target):
faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32) faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32)
setattr(target, 'faces', faces) setattr(target, 'faces', faces)
class PropertyGetter(dict):
def __getitem__(self, key):
semantic = 0
if isinstance(key, tuple):
key, semantic = key
return dict.__getitem__(self, (key, semantic))
def keys(self):
for k in dict.keys(self):
yield k[0]
def __iter__(self):
return self.keys()
def items(self):
for k, v in dict.items(self):
yield k[0], v
def _get_properties(properties, length): def _get_properties(properties, length):
""" """
Convenience Function to get the material properties as a dict Convenience Function to get the material properties as a dict
@ -346,7 +367,7 @@ def _get_properties(properties, length):
for p in [properties[i] for i in range(length)]: for p in [properties[i] for i in range(length)]:
#the name #the name
p = p.contents p = p.contents
key = str(p.mKey.data).split('.')[1] key = (str(p.mKey.data.decode("utf-8")).split('.')[1], p.mSemantic)
#the data #the data
from ctypes import POINTER, cast, c_int, c_float, sizeof from ctypes import POINTER, cast, c_int, c_float, sizeof
@ -354,7 +375,7 @@ def _get_properties(properties, length):
arr = cast(p.mData, POINTER(c_float * int(p.mDataLength/sizeof(c_float)) )).contents arr = cast(p.mData, POINTER(c_float * int(p.mDataLength/sizeof(c_float)) )).contents
value = [x for x in arr] value = [x for x in arr]
elif p.mType == 3: #string can't be an array elif p.mType == 3: #string can't be an array
value = cast(p.mData, POINTER(structs.String)).contents.data value = cast(p.mData, POINTER(structs.MaterialPropertyString)).contents.data.decode("utf-8")
elif p.mType == 4: elif p.mType == 4:
arr = cast(p.mData, POINTER(c_int * int(p.mDataLength/sizeof(c_int)) )).contents arr = cast(p.mData, POINTER(c_int * int(p.mDataLength/sizeof(c_int)) )).contents
value = [x for x in arr] value = [x for x in arr]
@ -366,7 +387,7 @@ def _get_properties(properties, length):
result[key] = value result[key] = value
return result return PropertyGetter(result)
def decompose_matrix(matrix): def decompose_matrix(matrix):
if not isinstance(matrix, structs.Matrix4x4): if not isinstance(matrix, structs.Matrix4x4):

View File

@ -154,5 +154,15 @@ def search_library():
# XXX: take version postfix of the .so on linux? # XXX: take version postfix of the .so on linux?
return res[1:] return res[1:]
def hasattr_silent(object, name):
"""
Calls hasttr() with the given parameters and preserves the legacy (pre-Python 3.2)
functionality of silently catching exceptions.
Returns the result of hasatter() or False if an exception was raised.
"""
try:
return hasattr(object, name)
except:
return False

View File

@ -1,6 +1,6 @@
#-*- coding: UTF-8 -*- #-*- coding: UTF-8 -*-
from ctypes import POINTER, c_void_p, c_int, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t from ctypes import POINTER, c_void_p, c_int, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t, c_uint32
class Vector2D(Structure): class Vector2D(Structure):
@ -82,6 +82,26 @@ class String(Structure):
("data", c_char*MAXLEN), ("data", c_char*MAXLEN),
] ]
class MaterialPropertyString(Structure):
"""
See 'aiTypes.h' for details.
The size of length is truncated to 4 bytes on 64-bit platforms when used as a
material property (see MaterialSystem.cpp aiMaterial::AddProperty() for details).
"""
MAXLEN = 1024
_fields_ = [
# Binary length of the string excluding the terminal 0. This is NOT the
# logical length of strings containing UTF-8 multibyte sequences! It's
# the number of bytes from the beginning of the string to its end.
("length", c_uint32),
# String buffer. Size limit is MAXLEN
("data", c_char*MAXLEN),
]
class MemoryInfo(Structure): class MemoryInfo(Structure):
""" """
See 'aiTypes.h' for details. See 'aiTypes.h' for details.

View File

@ -1,90 +0,0 @@
#!/usr/bin/env python
#-*- coding: UTF-8 -*-
"""
This module demonstrates the functionality of PyAssimp.
"""
import pyassimp.core as pyassimp
import os, sys
#get a model out of assimp's test-data if none is provided on the command line
DEFAULT_MODEL = os.path.join(os.path.dirname(__file__),
"..", "..",
"test", "models", "MDL", "MDL3 (3DGS A4)", "minigun.MDL")
def recur_node(node,level = 0):
print(" " + "\t" * level + "- " + str(node))
for child in node.children:
recur_node(child, level + 1)
def main(filename=None):
filename = filename or DEFAULT_MODEL
print "Reading model", filename
scene = pyassimp.load(filename)
#the model we load
print "MODEL:", filename
print
#write some statistics
print "SCENE:"
print " meshes:", len(scene.meshes)
print " materials:", len(scene.materials)
print " textures:", len(scene.textures)
print
print "NODES:"
recur_node(scene.rootnode)
print
print "MESHES:"
for index, mesh in enumerate(scene.meshes):
print " MESH", index+1
print " material id:", mesh.materialindex+1
print " vertices:", len(mesh.vertices)
print " first 3 verts:", mesh.vertices[:3]
if len(mesh.normals) > 0:
print " first 3 normals:", mesh.normals[:3]
else:
print " no normals"
print " colors:", len(mesh.colors)
tc = mesh.texturecoords
if len(tc) >= 4:
print " texture-coords 1:", len(tc[0]), "first3:", tc[0][:3]
print " texture-coords 2:", len(tc[1]), "first3:", tc[1][:3]
print " texture-coords 3:", len(tc[2]), "first3:", tc[2][:3]
print " texture-coords 4:", len(tc[3]), "first3:", tc[3][:3]
elif len(tc) == 0:
print " no texture coordinates"
else:
print " tc is an unexpected number of elements (expect 4, got", len(tc), ")"
print " uv-component-count:", len(mesh.numuvcomponents)
print " faces:", len(mesh.faces), "first:", [f for f in mesh.faces[:3]]
print " bones:", len(mesh.bones), "first:", [str(b) for b in mesh.bones[:3]]
print
print "MATERIALS:"
for index, material in enumerate(scene.materials):
print(" MATERIAL (id:" + str(index+1) + ")")
for key, value in material.properties.items():
print " %s: %s" % (key, value)
print
print "TEXTURES:"
for index, texture in enumerate(scene.textures):
print " TEXTURE", index+1
print " width:", texture.width
print " height:", texture.height
print " hint:", texture.achformathint
print " data (size):", len(texture.data)
# Finally release the model
pyassimp.release(scene)
print "Finished parsing the model."
if __name__ == "__main__":
main(sys.argv[1] if len(sys.argv)>1 else None)

View File

@ -6,23 +6,25 @@
It make a large use of shaders to illustrate a 'modern' OpenGL pipeline. It make a large use of shaders to illustrate a 'modern' OpenGL pipeline.
Based on: Based on:
- pygame + mouselook code from http://3dengine.org/Spectator_%28PyOpenGL%29 - pygame + mouselook code from http://3dengine.org/Spectator_%28PyOpenGL%29
- http://www.lighthouse3d.com/tutorials - http://www.lighthouse3d.com/tutorials
- http://www.songho.ca/opengl/gl_transform.html - http://www.songho.ca/opengl/gl_transform.html
- http://code.activestate.com/recipes/325391/ - http://code.activestate.com/recipes/325391/
- ASSIMP's C++ SimpleOpenGL viewer - ASSIMP's C++ SimpleOpenGL viewer
Authors: SĂ©verin Lemaignan, 2012-2013
""" """
import sys import sys
import logging import logging
logger = logging.getLogger("underworlds.3d_viewer") logger = logging.getLogger("pyassimp")
gllogger = logging.getLogger("OpenGL") gllogger = logging.getLogger("OpenGL")
gllogger.setLevel(logging.WARNING) gllogger.setLevel(logging.WARNING)
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
import OpenGL import OpenGL
#OpenGL.ERROR_CHECKING=False OpenGL.ERROR_CHECKING=False
#OpenGL.ERROR_LOGGING = False OpenGL.ERROR_LOGGING = False
#OpenGL.ERROR_ON_COPY = True #OpenGL.ERROR_ON_COPY = True
#OpenGL.FULL_LOGGING = True #OpenGL.FULL_LOGGING = True
from OpenGL.GL import * from OpenGL.GL import *
@ -38,7 +40,7 @@ import math, random
import numpy import numpy
from numpy import linalg from numpy import linalg
from pyassimp import core as pyassimp import pyassimp
from pyassimp.postprocess import * from pyassimp.postprocess import *
from pyassimp.helper import * from pyassimp.helper import *
@ -289,8 +291,13 @@ class PyAssimp3DViewer:
stride = 24 # 6 * 4 bytes stride = 24 # 6 * 4 bytes
glUniform4f( shader.Material_diffuse, *mesh.material.properties["diffuse"] ) diffuse = mesh.material.properties["diffuse"]
glUniform4f( shader.Material_ambient, *mesh.material.properties["ambient"] ) if len(diffuse) == 3: diffuse.append(1.0)
ambient = mesh.material.properties["ambient"]
if len(ambient) == 3: ambient.append(1.0)
glUniform4f( shader.Material_diffuse, *diffuse )
glUniform4f( shader.Material_ambient, *ambient )
vbo = mesh.gl["vbo"] vbo = mesh.gl["vbo"]
vbo.bind() vbo.bind()
@ -403,8 +410,6 @@ if __name__ == '__main__':
app.render() app.render()
app.controls_3d(0) app.controls_3d(0)
if pygame.K_f in app.keys: pygame.display.toggle_fullscreen() if pygame.K_f in app.keys: pygame.display.toggle_fullscreen()
if pygame.K_s in app.keys: app.screenshot()
if pygame.K_v in app.keys: app.check_visibility()
if pygame.K_TAB in app.keys: app.cycle_cameras() if pygame.K_TAB in app.keys: app.cycle_cameras()
if pygame.K_ESCAPE in app.keys: if pygame.K_ESCAPE in app.keys:
break break

View File

@ -0,0 +1,13 @@
pyassimp examples
=================
- `sample.py`: shows how to load a model with pyassimp, and display some statistics.
- `3d_viewer.py`: an OpenGL 3D viewer that requires shaders
- `fixed_pipeline_3d_viewer`: an OpenGL 3D viewer using the old fixed-pipeline.
Only for illustration example. Base new projects on `3d_viewer.py`.
Requirements for the 3D viewers:
- `pyopengl` (on Ubuntu/Debian, `sudo apt-get install python-opengl`)
- `pygame` (on Ubuntu/Debian, `sudo apt-get install python-pygame`)

View File

@ -35,7 +35,7 @@ logging.basicConfig(level=logging.INFO)
import math import math
import numpy import numpy
from pyassimp import core as pyassimp import pyassimp
from pyassimp.postprocess import * from pyassimp.postprocess import *
from pyassimp.helper import * from pyassimp.helper import *
@ -204,7 +204,6 @@ class GLRenderer():
""" """
if not hasattr(mat, "gl_mat"): # evaluate once the mat properties, and cache the values in a glDisplayList. if not hasattr(mat, "gl_mat"): # evaluate once the mat properties, and cache the values in a glDisplayList.
diffuse = numpy.array(mat.properties.get("diffuse", [0.8, 0.8, 0.8, 1.0])) diffuse = numpy.array(mat.properties.get("diffuse", [0.8, 0.8, 0.8, 1.0]))
specular = numpy.array(mat.properties.get("specular", [0., 0., 0., 1.0])) specular = numpy.array(mat.properties.get("specular", [0., 0., 0., 1.0]))
ambient = numpy.array(mat.properties.get("ambient", [0.2, 0.2, 0.2, 1.0])) ambient = numpy.array(mat.properties.get("ambient", [0.2, 0.2, 0.2, 1.0]))
@ -234,14 +233,6 @@ class GLRenderer():
gl_time = glutGet(GLUT_ELAPSED_TIME) gl_time = glutGet(GLUT_ELAPSED_TIME)
# Compute the new position of the camera and set it
self.x += self.dp * self.lx * 0.01 * (gl_time-self.prev_time)
self.z += self.dp * self.lz * 0.01 * (gl_time-self.prev_time)
self.angle += self.drot * 0.1 * (gl_time-self.prev_time)
self.lx = math.sin(self.angle)
self.lz = -math.cos(self.angle)
self.set_default_camera()
self.angle = (gl_time - self.prev_time) * 0.1 self.angle = (gl_time - self.prev_time) * 0.1
self.prev_time = gl_time self.prev_time = gl_time

View File

@ -12,29 +12,32 @@ loading and querying of 3d models using pyassimp works.
import sys,os import sys,os
import sample import sample
from pyassimp import pyassimp,errors from pyassimp import errors
# paths to be walkd recursively # paths to be walkd recursively
basepaths = [os.path.join('..','..','test','models'), os.path.join('..','..','test','models-nonbsd')] basepaths = [os.path.join('..','..','..','test','models'), os.path.join('..','..','..','test','models-nonbsd')]
# file extensions to be considered # file extensions to be considered
extensions = ['.3ds','.x','.lwo','.obj','.md5mesh','.dxf','.ply','.stl','.dae','.md5anim','.lws','.irrmesh','.nff','.off','.blend'] extensions = ['.3ds','.x','.lwo','.obj','.md5mesh','.dxf','.ply','.stl','.dae','.md5anim','.lws','.irrmesh','.nff','.off','.blend']
def run_tests(): def run_tests():
ok,err = 0,0 ok,err = 0,0
for path in basepaths: for path in basepaths:
for root, dirs, files in os.walk(path): print("Looking for models in %s..." % path)
for afile in files: for root, dirs, files in os.walk(path):
base,ext = os.path.splitext(afile) for afile in files:
if ext in extensions: base,ext = os.path.splitext(afile)
try: if ext in extensions:
sample.main(os.path.join(root,afile)) try:
ok += 1 sample.main(os.path.join(root,afile))
except errors.AssimpError as error: ok += 1
# assimp error is fine, this is a controlled case except errors.AssimpError as error:
print error # assimp error is fine, this is a controlled case
err += 1 print error
print '** Loaded %s models, got controlled errors for %s files' % (ok,err) err += 1
except Exception:
print("Error encountered while loading <%s>"%os.path.join(root,afile))
print('** Loaded %s models, got controlled errors for %s files' % (ok,err))
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -7,9 +7,10 @@ This module demonstrates the functionality of PyAssimp.
import os, sys import os, sys
import logging import logging
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.INFO)
from pyassimp import core as pyassimp import pyassimp
import pyassimp.postprocess
def recur_node(node,level = 0): def recur_node(node,level = 0):
print(" " + "\t" * level + "- " + str(node)) print(" " + "\t" * level + "- " + str(node))
@ -19,7 +20,7 @@ def recur_node(node,level = 0):
def main(filename=None): def main(filename=None):
scene = pyassimp.load(filename) scene = pyassimp.load(filename, pyassimp.postprocess.aiProcess_Triangulate)
#the model we load #the model we load
print("MODEL:" + filename) print("MODEL:" + filename)
@ -48,7 +49,7 @@ def main(filename=None):
print(" no normals") print(" no normals")
print(" colors:" + str(len(mesh.colors))) print(" colors:" + str(len(mesh.colors)))
tcs = mesh.texturecoords tcs = mesh.texturecoords
if tcs: if tcs.any():
for index, tc in enumerate(tcs): for index, tc in enumerate(tcs):
print(" texture-coords "+ str(index) + ":" + str(len(tcs[index])) + "first3:" + str(tcs[index][:3])) print(" texture-coords "+ str(index) + ":" + str(len(tcs[index])) + "first3:" + str(tcs[index][:3]))
@ -77,5 +78,12 @@ def main(filename=None):
# Finally release the model # Finally release the model
pyassimp.release(scene) pyassimp.release(scene)
def usage():
print("Usage: sample.py <3d model>")
if __name__ == "__main__": if __name__ == "__main__":
main(sys.argv[1] if len(sys.argv)>1 else None)
if len(sys.argv) != 2:
usage()
else:
main(sys.argv[1])

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