Merge branch 'master' of github.com:assimp/assimp
Conflicts: code/ColladaLoader.cpppull/502/head
commit
c59878e427
|
@ -183,6 +183,52 @@ ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
|
|||
|
||||
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
|
||||
|
||||
|
||||
SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
|
||||
"Build the C4D importer, which relies on the non-free Melange SDK."
|
||||
)
|
||||
|
||||
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
IF ( MSVC )
|
||||
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/includes")
|
||||
|
||||
# pick the correct prebuilt library
|
||||
IF(MSVC11)
|
||||
SET(C4D_LIB_POSTFIX "_2012md")
|
||||
ELSEIF(MSVC10)
|
||||
SET(C4D_LIB_POSTFIX "_2010md")
|
||||
ELSEIF(MSVC90)
|
||||
SET(C4D_LIB_POSTFIX "_2008md")
|
||||
ELSE()
|
||||
MESSAGE( FATAL_ERROR
|
||||
"C4D is currently only supported with MSVC 9, 10, 11"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_CL_64)
|
||||
SET(C4D_LIB_ARCH_POSTFIX "_x64")
|
||||
ELSE()
|
||||
SET(C4D_LIB_ARCH_POSTFIX "")
|
||||
ENDIF()
|
||||
|
||||
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/lib/WIN")
|
||||
|
||||
SET(C4D_DEBUG_LIBRARY "${C4D_LIB_BASE_PATH}/debug/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib")
|
||||
SET(C4D_RELEASE_LIBRARY "${C4D_LIB_BASE_PATH}/release/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib")
|
||||
|
||||
# winsock and winmm are necessary dependencies of melange (this is undocumented, but true.)
|
||||
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
|
||||
ELSE ()
|
||||
MESSAGE( FATAL_ERROR
|
||||
"C4D is currently only available on Windows with melange SDK installed in contrib/Melange"
|
||||
)
|
||||
ENDIF ( MSVC )
|
||||
else (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
|
||||
ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
|
||||
|
||||
|
||||
ADD_SUBDIRECTORY( code/ )
|
||||
option ( ASSIMP_BUILD_ASSIMP_TOOLS
|
||||
"If the supplementary tools for Assimp are built in addition to the library."
|
||||
|
|
|
@ -396,7 +396,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
|
|||
}
|
||||
for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
|
||||
{
|
||||
register unsigned int index = aiSplit[p][q];
|
||||
unsigned int index = aiSplit[p][q];
|
||||
aiFace& face = meshOut->mFaces[q];
|
||||
|
||||
face.mIndices = new unsigned int[3];
|
||||
|
|
|
@ -294,7 +294,7 @@ void Discreet3DSExporter::WriteMaterials()
|
|||
WriteColor(color);
|
||||
}
|
||||
|
||||
aiShadingMode shading_mode;
|
||||
aiShadingMode shading_mode = aiShadingMode_Flat;
|
||||
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
|
||||
|
||||
|
|
|
@ -489,7 +489,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
|
||||
for (it = object.surfaces.begin(); it != end; ++it)
|
||||
{
|
||||
register unsigned int idx = (*it).mat;
|
||||
unsigned int idx = (*it).mat;
|
||||
if (idx >= needMat.size())
|
||||
{
|
||||
DefaultLogger::get()->error("AC3D: material index is out of range");
|
||||
|
@ -617,7 +617,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
it2 = (*it).entries.begin();
|
||||
|
||||
// either a closed or an unclosed line
|
||||
register unsigned int tmp = (unsigned int)(*it).entries.size();
|
||||
unsigned int tmp = (unsigned int)(*it).entries.size();
|
||||
if (0x2 == type)--tmp;
|
||||
for (unsigned int m = 0; m < tmp;++m)
|
||||
{
|
||||
|
|
|
@ -168,7 +168,7 @@ void Parser::LogInfo(const char* szWarn)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Parser::LogError(const char* szWarn)
|
||||
AI_WONT_RETURN void Parser::LogError(const char* szWarn)
|
||||
{
|
||||
ai_assert(NULL != szWarn);
|
||||
|
||||
|
|
|
@ -602,7 +602,7 @@ private:
|
|||
// -------------------------------------------------------------------
|
||||
//! Output an error to the logger
|
||||
//! \param szWarn Error message
|
||||
void LogError(const char* szWarn);
|
||||
AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a string, enclosed in double quotation marks
|
||||
|
|
|
@ -273,13 +273,13 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
|
|||
if (buffer) delete[] buffer;
|
||||
}
|
||||
|
||||
void * GetBufferPointer() { return buffer; };
|
||||
void * GetBufferPointer() { return buffer; }
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; };
|
||||
virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; };
|
||||
virtual size_t Tell() const { return cursor; };
|
||||
virtual void Flush() { };
|
||||
virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; }
|
||||
virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; }
|
||||
virtual size_t Tell() const { return cursor; }
|
||||
virtual void Flush() { }
|
||||
|
||||
virtual size_t FileSize() const
|
||||
{
|
||||
|
|
|
@ -127,12 +127,12 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void B3DImporter::Oops(){
|
||||
AI_WONT_RETURN void B3DImporter::Oops(){
|
||||
throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void B3DImporter::Fail( string str ){
|
||||
AI_WONT_RETURN void B3DImporter::Fail( string str ){
|
||||
#ifdef DEBUG_B3D
|
||||
cout<<"Error in B3D file data: "<<str<<endl;
|
||||
#endif
|
||||
|
|
|
@ -87,8 +87,8 @@ private:
|
|||
float weights[4];
|
||||
};
|
||||
|
||||
void Oops();
|
||||
void Fail( std::string str );
|
||||
AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
void ReadTEXS();
|
||||
void ReadBRUS();
|
||||
|
|
|
@ -413,7 +413,7 @@ float BVHLoader::GetNextTokenAsFloat()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Aborts the file reading with an exception
|
||||
void BVHLoader::ThrowException( const std::string& pError)
|
||||
AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError)
|
||||
{
|
||||
throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError));
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ protected:
|
|||
float GetNextTokenAsFloat();
|
||||
|
||||
/** Aborts the file reading with an exception */
|
||||
void ThrowException( const std::string& pError);
|
||||
AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
/** Constructs an animation for the motion data and stores it in the given scene */
|
||||
void CreateAnimation( aiScene* pScene);
|
||||
|
|
|
@ -0,0 +1,641 @@
|
|||
/*
|
||||
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 C4DImporter.cpp
|
||||
* @brief Implementation of the Cinema4D importer class.
|
||||
*/
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
// no #ifdefing here, Cinema4D support is carried out in a branch of assimp
|
||||
// where it is turned on in the CMake settings.
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# error C4D support is currently MSVC only
|
||||
#endif
|
||||
|
||||
#include "C4DImporter.h"
|
||||
#include "TinyFormatter.h"
|
||||
|
||||
#if defined(_M_X64) || defined(__amd64__)
|
||||
# define __C4D_64BIT
|
||||
#endif
|
||||
|
||||
#define __PC
|
||||
#include "c4d_file.h"
|
||||
#include "default_alien_overloads.h"
|
||||
|
||||
using namespace _melange_;
|
||||
|
||||
// overload this function and fill in your own unique data
|
||||
void GetWriterInfo(LONG &id, String &appname)
|
||||
{
|
||||
id = 2424226;
|
||||
appname = "Open Asset Import Library";
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Formatter;
|
||||
|
||||
namespace Assimp {
|
||||
template<> const std::string LogFunctions<C4DImporter>::log_prefix = "C4D: ";
|
||||
}
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Cinema4D Importer",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
aiImporterFlags_SupportBinaryFlavour,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"c4d"
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
C4DImporter::C4DImporter()
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
C4DImporter::~C4DImporter()
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
||||
{
|
||||
const std::string& extension = GetExtension(pFile);
|
||||
if (extension == "c4d") {
|
||||
return true;
|
||||
}
|
||||
|
||||
else if ((!extension.length() || checkSig) && pIOHandler) {
|
||||
// TODO
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiImporterDesc* C4DImporter::GetInfo () const
|
||||
{
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void C4DImporter::SetupProperties(const Importer* /*pImp*/)
|
||||
{
|
||||
// nothing to be done for the moment
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void C4DImporter::InternReadFile( const std::string& pFile,
|
||||
aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
|
||||
|
||||
if( file.get() == NULL) {
|
||||
ThrowException("failed to open file " + pFile);
|
||||
}
|
||||
|
||||
const size_t file_size = file->FileSize();
|
||||
|
||||
std::vector<uint8_t> mBuffer(file_size);
|
||||
file->Read(&mBuffer[0], 1, file_size);
|
||||
|
||||
Filename f;
|
||||
f.SetMemoryReadMode(&mBuffer[0], file_size);
|
||||
|
||||
// open document first
|
||||
BaseDocument* doc = LoadDocument(f, SCENEFILTER_OBJECTS | SCENEFILTER_MATERIALS);
|
||||
if(doc == NULL) {
|
||||
ThrowException("failed to read document " + pFile);
|
||||
}
|
||||
|
||||
pScene->mRootNode = new aiNode("<C4DRoot>");
|
||||
|
||||
// first convert all materials
|
||||
ReadMaterials(doc->GetFirstMaterial());
|
||||
|
||||
// process C4D scenegraph recursively
|
||||
try {
|
||||
RecurseHierarchy(doc->GetFirstObject(), pScene->mRootNode);
|
||||
}
|
||||
catch(...) {
|
||||
BOOST_FOREACH(aiMesh* mesh, meshes) {
|
||||
delete mesh;
|
||||
}
|
||||
BaseDocument::Free(doc);
|
||||
throw;
|
||||
}
|
||||
BaseDocument::Free(doc);
|
||||
|
||||
// copy meshes over
|
||||
pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
|
||||
std::copy(meshes.begin(), meshes.end(), pScene->mMeshes);
|
||||
|
||||
// copy materials over, adding a default material if necessary
|
||||
unsigned int mat_count = static_cast<unsigned int>(materials.size());
|
||||
BOOST_FOREACH(aiMesh* mesh, meshes) {
|
||||
ai_assert(mesh->mMaterialIndex <= mat_count);
|
||||
if(mesh->mMaterialIndex >= mat_count) {
|
||||
++mat_count;
|
||||
|
||||
ScopeGuard<aiMaterial> def_material(new aiMaterial());
|
||||
const aiString name(AI_DEFAULT_MATERIAL_NAME);
|
||||
def_material->AddProperty(&name, AI_MATKEY_NAME);
|
||||
|
||||
materials.push_back(def_material.dismiss());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
|
||||
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
|
||||
std::copy(materials.begin(), materials.end(), pScene->mMaterials);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool C4DImporter::ReadShader(aiMaterial* out, _melange_::BaseShader* shader)
|
||||
{
|
||||
// based on Melange sample code (C4DImportExport.cpp)
|
||||
while(shader) {
|
||||
if(shader->GetType() == Xlayer) {
|
||||
BaseContainer* container = shader->GetDataInstance();
|
||||
GeData blend = container->GetData(SLA_LAYER_BLEND);
|
||||
iBlendDataType* blend_list = reinterpret_cast<iBlendDataType*>(blend.GetCustomDataType(CUSTOMDATA_BLEND_LIST));
|
||||
if (!blend_list)
|
||||
{
|
||||
LogWarn("ignoring XLayer shader: no blend list given");
|
||||
continue;
|
||||
}
|
||||
|
||||
LayerShaderLayer *lsl = dynamic_cast<LayerShaderLayer*>(blend_list->m_BlendLayers.GetObject(0));
|
||||
|
||||
// Ignore the actual layer blending - models for real-time rendering should not
|
||||
// use them in a non-trivial way. Just try to find textures that we can apply
|
||||
// to the model.
|
||||
while (lsl)
|
||||
{
|
||||
if (lsl->GetType() == TypeFolder)
|
||||
{
|
||||
BlendFolder* const folder = dynamic_cast<BlendFolder*>(lsl);
|
||||
LayerShaderLayer *subLsl = dynamic_cast<LayerShaderLayer*>(folder->m_Children.GetObject(0));
|
||||
|
||||
while (subLsl)
|
||||
{
|
||||
if (subLsl->GetType() == TypeShader) {
|
||||
BlendShader* const shader = dynamic_cast<BlendShader*>(subLsl);
|
||||
if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
subLsl = subLsl->GetNext();
|
||||
}
|
||||
}
|
||||
else if (lsl->GetType() == TypeShader) {
|
||||
BlendShader* const shader = dynamic_cast<BlendShader*>(lsl);
|
||||
if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
lsl = lsl->GetNext();
|
||||
}
|
||||
}
|
||||
else if ( shader->GetType() == Xbitmap )
|
||||
{
|
||||
aiString path;
|
||||
shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
|
||||
path.length = ::strlen(path.data);
|
||||
out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType())));
|
||||
}
|
||||
shader = shader->GetNext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void C4DImporter::ReadMaterials(_melange_::BaseMaterial* mat)
|
||||
{
|
||||
// based on Melange sample code
|
||||
while (mat)
|
||||
{
|
||||
const String& name = mat->GetName();
|
||||
if (mat->GetType() == Mmaterial)
|
||||
{
|
||||
aiMaterial* out = new aiMaterial();
|
||||
material_mapping[mat] = static_cast<unsigned int>(materials.size());
|
||||
materials.push_back(out);
|
||||
|
||||
aiString ai_name;
|
||||
name.GetCString(ai_name.data, MAXLEN-1);
|
||||
ai_name.length = ::strlen(ai_name.data);
|
||||
out->AddProperty(&ai_name, AI_MATKEY_NAME);
|
||||
|
||||
Material& m = dynamic_cast<Material&>(*mat);
|
||||
|
||||
if (m.GetChannelState(CHANNEL_COLOR))
|
||||
{
|
||||
GeData data;
|
||||
mat->GetParameter(MATERIAL_COLOR_COLOR, data);
|
||||
Vector color = data.GetVector();
|
||||
mat->GetParameter(MATERIAL_COLOR_BRIGHTNESS, data);
|
||||
const Real brightness = data.GetReal();
|
||||
|
||||
color *= brightness;
|
||||
|
||||
aiVector3D v;
|
||||
v.x = color.x;
|
||||
v.y = color.y;
|
||||
v.z = color.z;
|
||||
out->AddProperty(&v, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
}
|
||||
|
||||
BaseShader* const shader = m.GetShader(MATERIAL_COLOR_SHADER);
|
||||
if(shader) {
|
||||
ReadShader(out, shader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType())));
|
||||
}
|
||||
mat = mat->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
|
||||
{
|
||||
ai_assert(parent != NULL);
|
||||
std::vector<aiNode*> nodes;
|
||||
|
||||
// based on Melange sample code
|
||||
while (object)
|
||||
{
|
||||
const String& name = object->GetName();
|
||||
const LONG type = object->GetType();
|
||||
const Matrix& ml = object->GetMl();
|
||||
|
||||
aiString string;
|
||||
name.GetCString(string.data, MAXLEN-1);
|
||||
string.length = ::strlen(string.data);
|
||||
aiNode* const nd = new aiNode();
|
||||
|
||||
nd->mParent = parent;
|
||||
nd->mName = string;
|
||||
|
||||
nd->mTransformation.a1 = ml.v1.x;
|
||||
nd->mTransformation.b1 = ml.v1.y;
|
||||
nd->mTransformation.c1 = ml.v1.z;
|
||||
|
||||
nd->mTransformation.a2 = ml.v2.x;
|
||||
nd->mTransformation.b2 = ml.v2.y;
|
||||
nd->mTransformation.c2 = ml.v2.z;
|
||||
|
||||
nd->mTransformation.a3 = ml.v3.x;
|
||||
nd->mTransformation.b3 = ml.v3.y;
|
||||
nd->mTransformation.c3 = ml.v3.z;
|
||||
|
||||
nd->mTransformation.a4 = ml.off.x;
|
||||
nd->mTransformation.b4 = ml.off.y;
|
||||
nd->mTransformation.c4 = ml.off.z;
|
||||
|
||||
nodes.push_back(nd);
|
||||
|
||||
GeData data;
|
||||
if (type == Ocamera)
|
||||
{
|
||||
object->GetParameter(CAMERAOBJECT_FOV, data);
|
||||
// TODO: read camera
|
||||
}
|
||||
else if (type == Olight)
|
||||
{
|
||||
// TODO: read light
|
||||
}
|
||||
else if (type == Opolygon)
|
||||
{
|
||||
aiMesh* const mesh = ReadMesh(object);
|
||||
if(mesh != NULL) {
|
||||
nd->mNumMeshes = 1;
|
||||
nd->mMeshes = new unsigned int[1];
|
||||
nd->mMeshes[0] = static_cast<unsigned int>(meshes.size());
|
||||
meshes.push_back(mesh);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogWarn("ignoring object: " + std::string(GetObjectTypeName(type)));
|
||||
}
|
||||
|
||||
RecurseHierarchy(object->GetDown(), nd);
|
||||
object = object->GetNext();
|
||||
}
|
||||
|
||||
// copy nodes over to parent
|
||||
parent->mNumChildren = static_cast<unsigned int>(nodes.size());
|
||||
parent->mChildren = new aiNode*[parent->mNumChildren]();
|
||||
std::copy(nodes.begin(), nodes.end(), parent->mChildren);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiMesh* C4DImporter::ReadMesh(BaseObject* object)
|
||||
{
|
||||
assert(object != NULL && object->GetType() == Opolygon);
|
||||
|
||||
// based on Melange sample code
|
||||
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
|
||||
ai_assert(polyObject != NULL);
|
||||
|
||||
const LONG pointCount = polyObject->GetPointCount();
|
||||
const LONG polyCount = polyObject->GetPolygonCount();
|
||||
if(!polyObject || !pointCount) {
|
||||
LogWarn("ignoring mesh with zero vertices or faces");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Vector* points = polyObject->GetPointR();
|
||||
ai_assert(points != NULL);
|
||||
|
||||
const CPolygon* polys = polyObject->GetPolygonR();
|
||||
ai_assert(polys != NULL);
|
||||
|
||||
ScopeGuard<aiMesh> mesh(new aiMesh());
|
||||
mesh->mNumFaces = static_cast<unsigned int>(polyCount);
|
||||
aiFace* face = mesh->mFaces = new aiFace[mesh->mNumFaces]();
|
||||
|
||||
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
mesh->mMaterialIndex = 0;
|
||||
|
||||
unsigned int vcount = 0;
|
||||
|
||||
// first count vertices
|
||||
for (LONG i = 0; i < polyCount; i++)
|
||||
{
|
||||
vcount += 3;
|
||||
|
||||
// TODO: do we also need to handle lines or points with similar checks?
|
||||
if (polys[i].c != polys[i].d)
|
||||
{
|
||||
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||
++vcount;
|
||||
}
|
||||
}
|
||||
|
||||
ai_assert(vcount > 0);
|
||||
|
||||
mesh->mNumVertices = vcount;
|
||||
aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
aiVector3D* normals, *uvs, *tangents, *bitangents;
|
||||
unsigned int n = 0;
|
||||
|
||||
// check if there are normals, tangents or UVW coordinates
|
||||
BaseTag* tag = object->GetTag(Tnormal);
|
||||
NormalTag* normals_src = NULL;
|
||||
if(tag) {
|
||||
normals_src = dynamic_cast<NormalTag*>(tag);
|
||||
normals = mesh->mNormals = new aiVector3D[mesh->mNumVertices]();
|
||||
}
|
||||
|
||||
tag = object->GetTag(Ttangent);
|
||||
TangentTag* tangents_src = NULL;
|
||||
if(tag) {
|
||||
tangents_src = dynamic_cast<TangentTag*>(tag);
|
||||
tangents = mesh->mTangents = new aiVector3D[mesh->mNumVertices]();
|
||||
bitangents = mesh->mBitangents = new aiVector3D[mesh->mNumVertices]();
|
||||
}
|
||||
|
||||
tag = object->GetTag(Tuvw);
|
||||
UVWTag* uvs_src = NULL;
|
||||
if(tag) {
|
||||
uvs_src = dynamic_cast<UVWTag*>(tag);
|
||||
uvs = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]();
|
||||
}
|
||||
|
||||
// copy vertices and extra channels over and populate faces
|
||||
for (LONG i = 0; i < polyCount; ++i, ++face)
|
||||
{
|
||||
ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
|
||||
const Vector& pointA = points[polys[i].a];
|
||||
verts->x = pointA.x;
|
||||
verts->y = pointA.y;
|
||||
verts->z = pointA.z;
|
||||
++verts;
|
||||
|
||||
ai_assert(polys[i].b < pointCount && polys[i].b >= 0);
|
||||
const Vector& pointB = points[polys[i].b];
|
||||
verts->x = pointB.x;
|
||||
verts->y = pointB.y;
|
||||
verts->z = pointB.z;
|
||||
++verts;
|
||||
|
||||
ai_assert(polys[i].c < pointCount && polys[i].c >= 0);
|
||||
const Vector& pointC = points[polys[i].c];
|
||||
verts->x = pointC.x;
|
||||
verts->y = pointC.y;
|
||||
verts->z = pointC.z;
|
||||
++verts;
|
||||
|
||||
// TODO: do we also need to handle lines or points with similar checks?
|
||||
if (polys[i].c != polys[i].d)
|
||||
{
|
||||
ai_assert(polys[i].d < pointCount && polys[i].d >= 0);
|
||||
|
||||
face->mNumIndices = 4;
|
||||
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||
const Vector& pointD = points[polys[i].d];
|
||||
verts->x = pointD.x;
|
||||
verts->y = pointD.y;
|
||||
verts->z = pointD.z;
|
||||
++verts;
|
||||
}
|
||||
else {
|
||||
face->mNumIndices = 3;
|
||||
}
|
||||
face->mIndices = new unsigned int[face->mNumIndices];
|
||||
for(unsigned int j = 0; j < face->mNumIndices; ++j) {
|
||||
face->mIndices[j] = n++;
|
||||
}
|
||||
|
||||
// copy normals
|
||||
if (normals_src) {
|
||||
if(i >= normals_src->GetNormalCount()) {
|
||||
LogError("unexpected number of normals, ignoring");
|
||||
}
|
||||
else {
|
||||
const NormalStruct& nor = normals_src->GetNormals(i);
|
||||
normals->x = nor.a.x;
|
||||
normals->y = nor.a.y;
|
||||
normals->z = nor.a.z;
|
||||
++normals;
|
||||
|
||||
normals->x = nor.b.x;
|
||||
normals->y = nor.b.y;
|
||||
normals->z = nor.b.z;
|
||||
++normals;
|
||||
|
||||
normals->x = nor.c.x;
|
||||
normals->y = nor.c.y;
|
||||
normals->z = nor.c.z;
|
||||
++normals;
|
||||
|
||||
if(face->mNumIndices == 4) {
|
||||
normals->x = nor.d.x;
|
||||
normals->y = nor.d.y;
|
||||
normals->z = nor.d.z;
|
||||
++normals;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy tangents and bitangents
|
||||
if (tangents_src) {
|
||||
|
||||
for(unsigned int k = 0; k < face->mNumIndices; ++k) {
|
||||
LONG l;
|
||||
switch(k) {
|
||||
case 0:
|
||||
l = polys[i].a;
|
||||
break;
|
||||
case 1:
|
||||
l = polys[i].b;
|
||||
break;
|
||||
case 2:
|
||||
l = polys[i].c;
|
||||
break;
|
||||
case 3:
|
||||
l = polys[i].d;
|
||||
break;
|
||||
default:
|
||||
ai_assert(false);
|
||||
}
|
||||
if(l >= tangents_src->GetDataCount()) {
|
||||
LogError("unexpected number of tangents, ignoring");
|
||||
break;
|
||||
}
|
||||
|
||||
Tangent tan = tangents_src->GetDataR()[l];
|
||||
tangents->x = tan.vl.x;
|
||||
tangents->y = tan.vl.y;
|
||||
tangents->z = tan.vl.z;
|
||||
++tangents;
|
||||
|
||||
bitangents->x = tan.vr.x;
|
||||
bitangents->y = tan.vr.y;
|
||||
bitangents->z = tan.vr.z;
|
||||
++bitangents;
|
||||
}
|
||||
}
|
||||
|
||||
// copy UVs
|
||||
if (uvs_src) {
|
||||
if(i >= uvs_src->GetDataCount()) {
|
||||
LogError("unexpected number of UV coordinates, ignoring");
|
||||
}
|
||||
else {
|
||||
UVWStruct uvw;
|
||||
uvs_src->Get(uvs_src->GetDataAddressR(),i,uvw);
|
||||
|
||||
uvs->x = uvw.a.x;
|
||||
uvs->y = 1.0f-uvw.a.y;
|
||||
uvs->z = uvw.a.z;
|
||||
++uvs;
|
||||
|
||||
uvs->x = uvw.b.x;
|
||||
uvs->y = 1.0f-uvw.b.y;
|
||||
uvs->z = uvw.b.z;
|
||||
++uvs;
|
||||
|
||||
uvs->x = uvw.c.x;
|
||||
uvs->y = 1.0f-uvw.c.y;
|
||||
uvs->z = uvw.c.z;
|
||||
++uvs;
|
||||
|
||||
if(face->mNumIndices == 4) {
|
||||
uvs->x = uvw.d.x;
|
||||
uvs->y = 1.0f-uvw.d.y;
|
||||
uvs->z = uvw.d.z;
|
||||
++uvs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh->mMaterialIndex = ResolveMaterial(polyObject);
|
||||
return mesh.dismiss();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
|
||||
{
|
||||
ai_assert(obj != NULL);
|
||||
|
||||
const unsigned int mat_count = static_cast<unsigned int>(materials.size());
|
||||
|
||||
BaseTag* tag = obj->GetTag(Ttexture);
|
||||
if(tag == NULL) {
|
||||
return mat_count;
|
||||
}
|
||||
|
||||
TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
|
||||
|
||||
BaseMaterial* const mat = ttag.GetMaterial();
|
||||
assert(mat != NULL);
|
||||
|
||||
const MaterialMap::const_iterator it = material_mapping.find(mat);
|
||||
if(it == material_mapping.end()) {
|
||||
return mat_count;
|
||||
}
|
||||
|
||||
ai_assert((*it).second < mat_count);
|
||||
return (*it).second;
|
||||
}
|
|
@ -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 C4DImporter.h
|
||||
* @brief Declaration of the Cinema4D (*.c4d) importer class.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_CINEMA_4D_LOADER_H
|
||||
#define INCLUDED_AI_CINEMA_4D_LOADER_H
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "LogAux.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
struct aiImporterDesc;
|
||||
|
||||
namespace _melange_ {
|
||||
class BaseObject; // c4d_file.h
|
||||
class PolygonObject;
|
||||
class BaseMaterial;
|
||||
class BaseShader;
|
||||
}
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// TinyFormatter.h
|
||||
namespace Formatter {
|
||||
template <typename T,typename TR, typename A> class basic_formatter;
|
||||
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/** Importer class to load Cinema4D files using the Melange library to be obtained from
|
||||
* www.plugincafe.com
|
||||
*
|
||||
* Note that Melange is not free software. */
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter>
|
||||
{
|
||||
public:
|
||||
|
||||
C4DImporter();
|
||||
~C4DImporter();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// --------------------
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||
bool checkSig) const;
|
||||
|
||||
protected:
|
||||
|
||||
// --------------------
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
|
||||
// --------------------
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
// --------------------
|
||||
void InternReadFile( const std::string& pFile, aiScene* pScene,
|
||||
IOSystem* pIOHandler);
|
||||
|
||||
private:
|
||||
|
||||
void ReadMaterials(_melange_::BaseMaterial* mat);
|
||||
void RecurseHierarchy(_melange_::BaseObject* object, aiNode* parent);
|
||||
aiMesh* ReadMesh(_melange_::BaseObject* object);
|
||||
unsigned int ResolveMaterial(_melange_::PolygonObject* obj);
|
||||
|
||||
bool ReadShader(aiMaterial* out, _melange_::BaseShader* shader);
|
||||
|
||||
std::vector<aiMesh*> meshes;
|
||||
std::vector<aiMaterial*> materials;
|
||||
|
||||
typedef std::map<_melange_::BaseMaterial*, unsigned int> MaterialMap;
|
||||
MaterialMap material_mapping;
|
||||
|
||||
}; // !class C4DImporter
|
||||
|
||||
} // end of namespace Assimp
|
||||
#endif // INCLUDED_AI_CINEMA_4D_LOADER_H
|
||||
|
|
@ -148,6 +148,14 @@ SET( Common_SRCS
|
|||
)
|
||||
SOURCE_GROUP(Common FILES ${Common_SRCS})
|
||||
|
||||
IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
|
||||
SET( C4D_SRCS
|
||||
C4DImporter.cpp
|
||||
C4DImporter.h
|
||||
)
|
||||
SOURCE_GROUP( C4D FILES ${C4D_SRCS})
|
||||
ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
|
||||
|
||||
SET( 3DS_SRCS
|
||||
3DSConverter.cpp
|
||||
3DSHelper.h
|
||||
|
@ -718,6 +726,11 @@ SET( assimp_src
|
|||
AssimpPCH.cpp
|
||||
)
|
||||
|
||||
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
SET( assimp_src ${assimp_src} ${C4D_SRCS})
|
||||
INCLUDE_DIRECTORIES(${C4D_INCLUDES})
|
||||
ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
|
||||
#ADD_MSVC_PRECOMPILED_HEADER("AssimpPCH.h" "AssimpPCH.cpp" assimp_src)
|
||||
|
||||
ADD_LIBRARY( assimp ${assimp_src} )
|
||||
|
@ -730,6 +743,12 @@ if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
|
|||
target_link_libraries(assimp android_jniiosystem)
|
||||
endif(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
|
||||
|
||||
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
TARGET_LINK_LIBRARIES(assimp optimized ${C4D_RELEASE_LIBRARY})
|
||||
TARGET_LINK_LIBRARIES(assimp debug ${C4D_DEBUG_LIBRARY})
|
||||
TARGET_LINK_LIBRARIES(assimp ${C4D_EXTRA_LIBRARIES})
|
||||
ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
|
||||
if( MSVC )
|
||||
# in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
|
||||
if( MSVC70 OR MSVC71 )
|
||||
|
|
|
@ -127,7 +127,7 @@ void COBImporter::SetupProperties(const Importer* /*pImp*/)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/*static*/ void COBImporter::ThrowException(const std::string& msg)
|
||||
/*static*/ AI_WONT_RETURN void COBImporter::ThrowException(const std::string& msg)
|
||||
{
|
||||
throw DeadlyImportError("COB: "+msg);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ private:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
/** Prepend 'COB: ' and throw msg.*/
|
||||
static void ThrowException(const std::string& msg);
|
||||
AI_WONT_RETURN static void ThrowException(const std::string& msg) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Read from an ascii scene/object file
|
||||
|
|
|
@ -167,7 +167,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
// their tangent vectors are set to qnan.
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
{
|
||||
register unsigned int idx = face.mIndices[i];
|
||||
unsigned int idx = face.mIndices[i];
|
||||
vertexDone [idx] = true;
|
||||
meshTang [idx] = aiVector3D(qnan);
|
||||
meshBitang [idx] = aiVector3D(qnan);
|
||||
|
|
|
@ -452,7 +452,7 @@ void ColladaExporter::WriteMaterials()
|
|||
}
|
||||
}
|
||||
|
||||
aiShadingMode shading;
|
||||
aiShadingMode shading = aiShadingMode_Flat;
|
||||
materials[a].shading_model = "phong";
|
||||
if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
|
||||
if(shading == aiShadingMode_Phong) {
|
||||
|
|
|
@ -395,6 +395,7 @@ struct Controller
|
|||
/** A collada material. Pretty much the only member is a reference to an effect. */
|
||||
struct Material
|
||||
{
|
||||
std::string mName;
|
||||
std::string mEffect;
|
||||
};
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
ColladaLoader::ColladaLoader()
|
||||
: noSkeletonMesh(), ignoreUpDirection(false), mNodeNameCounter()
|
||||
: noSkeletonMesh(), ignoreUpDirection(false), mNodeNameCounter()
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -94,9 +94,9 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
|
|||
// XML - too generic, we need to open the file and search for typical keywords
|
||||
if( extension == "xml" || !extension.length() || checkSig) {
|
||||
/* If CanRead() is called in order to check whether we
|
||||
* support a specific file extension in general pIOHandler
|
||||
* might be NULL and it's our duty to return true here.
|
||||
*/
|
||||
* support a specific file extension in general pIOHandler
|
||||
* might be NULL and it's our duty to return true here.
|
||||
*/
|
||||
if (!pIOHandler)return true;
|
||||
const char* tokens[] = {"collada"};
|
||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
||||
|
@ -157,26 +157,26 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
|||
// ... then fill the materials with the now adjusted settings
|
||||
FillMaterials(parser, pScene);
|
||||
|
||||
// Apply unitsize scale calculation
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
|
||||
0, parser.mUnitSize, 0, 0,
|
||||
0, 0, parser.mUnitSize, 0,
|
||||
0, 0, 0, 1);
|
||||
if( !ignoreUpDirection ) {
|
||||
// Convert to Y_UP, if different orientation
|
||||
// Apply unitsize scale calculation
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
|
||||
0, parser.mUnitSize, 0, 0,
|
||||
0, 0, parser.mUnitSize, 0,
|
||||
0, 0, 0, 1);
|
||||
if( !ignoreUpDirection ) {
|
||||
// Convert to Y_UP, if different orientation
|
||||
if( parser.mUpDirection == ColladaParser::UP_X)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
0, -1, 0, 0,
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
0, -1, 0, 0,
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
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);
|
||||
}
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
// store all meshes
|
||||
StoreSceneMeshes( pScene);
|
||||
|
||||
|
@ -251,14 +251,14 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Resolve node instances
|
||||
void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
|
||||
std::vector<const Collada::Node*>& resolved)
|
||||
std::vector<const Collada::Node*>& resolved)
|
||||
{
|
||||
// reserve enough storage
|
||||
resolved.reserve(pNode->mNodeInstances.size());
|
||||
|
||||
// ... and iterate through all nodes to be instanced as children of pNode
|
||||
for (std::vector<Collada::NodeInstance>::const_iterator it = pNode->mNodeInstances.begin(),
|
||||
end = pNode->mNodeInstances.end(); it != end; ++it)
|
||||
end = pNode->mNodeInstances.end(); it != end; ++it)
|
||||
{
|
||||
// find the corresponding node in the library
|
||||
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find((*it).mNode);
|
||||
|
@ -283,7 +283,7 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Resolve UV channels
|
||||
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
|
||||
const Collada::SemanticMappingTable& table)
|
||||
const Collada::SemanticMappingTable& table)
|
||||
{
|
||||
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
|
||||
if (it != table.mMap.end()) {
|
||||
|
@ -387,7 +387,7 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
|
|||
|
||||
// ... but for the rest some values are optional
|
||||
// and we need to compute the others in any combination.
|
||||
if (srcCamera->mAspect != 10e10f)
|
||||
if (srcCamera->mAspect != 10e10f)
|
||||
out->mAspect = srcCamera->mAspect;
|
||||
|
||||
if (srcCamera->mHorFov != 10e10f) {
|
||||
|
@ -395,12 +395,12 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
|
|||
|
||||
if (srcCamera->mVerFov != 10e10f && srcCamera->mAspect == 10e10f) {
|
||||
out->mAspect = tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
|
||||
tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
|
||||
tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
|
||||
}
|
||||
}
|
||||
else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
|
||||
out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(atan(srcCamera->mAspect *
|
||||
tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
|
||||
tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
|
||||
}
|
||||
|
||||
// Collada uses degrees, we use radians
|
||||
|
@ -518,11 +518,11 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|||
|
||||
// assign the material index
|
||||
dstMesh->mMaterialIndex = matIdx;
|
||||
if(dstMesh->mName.length == 0)
|
||||
{
|
||||
dstMesh->mName = mid.mMeshOrController;
|
||||
}
|
||||
}
|
||||
if(dstMesh->mName.length == 0)
|
||||
{
|
||||
dstMesh->mName = mid.mMeshOrController;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,11 +538,11 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
|
||||
aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
|
||||
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
|
||||
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
|
||||
{
|
||||
aiMesh* dstMesh = new aiMesh;
|
||||
|
||||
dstMesh->mName = pSrcMesh->mName;
|
||||
dstMesh->mName = pSrcMesh->mName;
|
||||
|
||||
// count the vertices addressed by its faces
|
||||
const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace,
|
||||
|
@ -624,8 +624,8 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|||
if( pSrcController)
|
||||
{
|
||||
// refuse if the vertex count does not match
|
||||
// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
|
||||
// throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count");
|
||||
// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
|
||||
// throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count");
|
||||
|
||||
// resolve references - joint names
|
||||
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
|
||||
|
@ -937,7 +937,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
|
||||
// find the collada node corresponding to the aiNode
|
||||
const Collada::Node* srcNode = FindNode( pParser.mRootNode, nodeName);
|
||||
// ai_assert( srcNode != NULL);
|
||||
// ai_assert( srcNode != NULL);
|
||||
if( !srcNode)
|
||||
continue;
|
||||
|
||||
|
@ -1058,154 +1058,134 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
if( e.mTimeAccessor->mCount != e.mValueAccessor->mCount)
|
||||
throw DeadlyImportError( boost::str( boost::format( "Time count / value count mismatch in animation channel \"%s\".") % e.mChannel->mTarget));
|
||||
|
||||
if( e.mTimeAccessor->mCount > 0 )
|
||||
{
|
||||
// find bounding times
|
||||
startTime = std::min( startTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, 0, 0));
|
||||
endTime = std::max( endTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, e.mTimeAccessor->mCount-1, 0));
|
||||
}
|
||||
if( e.mTimeAccessor->mCount > 0 )
|
||||
{
|
||||
// find bounding times
|
||||
startTime = std::min( startTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, 0, 0));
|
||||
endTime = std::max( endTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, e.mTimeAccessor->mCount-1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<aiMatrix4x4> resultTrafos;
|
||||
if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
|
||||
{
|
||||
// create a local transformation chain of the node's transforms
|
||||
std::vector<Collada::Transform> transforms = srcNode->mTransforms;
|
||||
std::vector<aiMatrix4x4> resultTrafos;
|
||||
if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
|
||||
{
|
||||
// create a local transformation chain of the node's transforms
|
||||
std::vector<Collada::Transform> transforms = srcNode->mTransforms;
|
||||
|
||||
// now for every unique point in time, find or interpolate the key values for that time
|
||||
// and apply them to the transform chain. Then the node's present transformation can be calculated.
|
||||
float time = startTime;
|
||||
while( 1)
|
||||
{
|
||||
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
||||
{
|
||||
Collada::ChannelEntry& e = *it;
|
||||
// now for every unique point in time, find or interpolate the key values for that time
|
||||
// and apply them to the transform chain. Then the node's present transformation can be calculated.
|
||||
float time = startTime;
|
||||
while( 1)
|
||||
{
|
||||
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
||||
{
|
||||
Collada::ChannelEntry& e = *it;
|
||||
|
||||
// find the keyframe behind the current point in time
|
||||
size_t pos = 0;
|
||||
float postTime = 0.f;
|
||||
while( 1)
|
||||
{
|
||||
if( pos >= e.mTimeAccessor->mCount)
|
||||
break;
|
||||
postTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
|
||||
if( postTime >= time)
|
||||
break;
|
||||
++pos;
|
||||
}
|
||||
// find the keyframe behind the current point in time
|
||||
size_t pos = 0;
|
||||
float postTime = 0.f;
|
||||
while( 1)
|
||||
{
|
||||
if( pos >= e.mTimeAccessor->mCount)
|
||||
break;
|
||||
postTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
|
||||
if( postTime >= time)
|
||||
break;
|
||||
++pos;
|
||||
}
|
||||
|
||||
pos = std::min( pos, e.mTimeAccessor->mCount-1);
|
||||
pos = std::min( pos, e.mTimeAccessor->mCount-1);
|
||||
|
||||
// read values from there
|
||||
float temp[16];
|
||||
for( size_t c = 0; c < e.mValueAccessor->mSize; ++c)
|
||||
temp[c] = ReadFloat( *e.mValueAccessor, *e.mValueData, pos, c);
|
||||
// read values from there
|
||||
float temp[16];
|
||||
for( size_t c = 0; c < e.mValueAccessor->mSize; ++c)
|
||||
temp[c] = ReadFloat( *e.mValueAccessor, *e.mValueData, pos, c);
|
||||
|
||||
// if not exactly at the key time, interpolate with previous value set
|
||||
if( postTime > time && pos > 0)
|
||||
{
|
||||
float preTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos-1, 0);
|
||||
float factor = (time - postTime) / (preTime - postTime);
|
||||
// if not exactly at the key time, interpolate with previous value set
|
||||
if( postTime > time && pos > 0)
|
||||
{
|
||||
float preTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos-1, 0);
|
||||
float factor = (time - postTime) / (preTime - postTime);
|
||||
|
||||
for( size_t c = 0; c < e.mValueAccessor->mSize; ++c)
|
||||
{
|
||||
float v = ReadFloat( *e.mValueAccessor, *e.mValueData, pos-1, c);
|
||||
temp[c] += (v - temp[c]) * factor;
|
||||
}
|
||||
}
|
||||
for( size_t c = 0; c < e.mValueAccessor->mSize; ++c)
|
||||
{
|
||||
float v = ReadFloat( *e.mValueAccessor, *e.mValueData, pos-1, c);
|
||||
temp[c] += (v - temp[c]) * factor;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply values to current transformation
|
||||
std::copy( temp, temp + e.mValueAccessor->mSize, transforms[e.mTransformIndex].f + e.mSubElement);
|
||||
}
|
||||
// Apply values to current transformation
|
||||
std::copy( temp, temp + e.mValueAccessor->mSize, transforms[e.mTransformIndex].f + e.mSubElement);
|
||||
}
|
||||
|
||||
// Calculate resulting transformation
|
||||
aiMatrix4x4 mat = pParser.CalculateResultTransform( transforms);
|
||||
// Calculate resulting transformation
|
||||
aiMatrix4x4 mat = pParser.CalculateResultTransform( transforms);
|
||||
|
||||
// out of lazyness: we store the time in matrix.d4
|
||||
mat.d4 = time;
|
||||
resultTrafos.push_back( mat);
|
||||
// out of lazyness: we store the time in matrix.d4
|
||||
mat.d4 = time;
|
||||
resultTrafos.push_back( mat);
|
||||
|
||||
// find next point in time to evaluate. That's the closest frame larger than the current in any channel
|
||||
float nextTime = 1e20f;
|
||||
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
||||
{
|
||||
Collada::ChannelEntry& e = *it;
|
||||
// find next point in time to evaluate. That's the closest frame larger than the current in any channel
|
||||
float nextTime = 1e20f;
|
||||
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
||||
{
|
||||
Collada::ChannelEntry& e = *it;
|
||||
|
||||
// find the next time value larger than the current
|
||||
size_t pos = 0;
|
||||
while( pos < e.mTimeAccessor->mCount)
|
||||
{
|
||||
float t = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
|
||||
if( t > time)
|
||||
{
|
||||
nextTime = std::min( nextTime, t);
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
// find the next time value larger than the current
|
||||
size_t pos = 0;
|
||||
while( pos < e.mTimeAccessor->mCount)
|
||||
{
|
||||
float t = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
|
||||
if( t > time)
|
||||
{
|
||||
nextTime = std::min( nextTime, t);
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/assimp/assimp/issues/458
|
||||
// Sub-sample axis-angle channels if the delta between two consecutive
|
||||
// key-frame angles is >= 180 degrees.
|
||||
if (transforms[e.mTransformIndex].mType == Collada::TF_ROTATE && e.mSubElement == 3 && pos > 0 && pos < e.mTimeAccessor->mCount) {
|
||||
float cur_key_angle = ReadFloat( *e.mValueAccessor, *e.mValueData, pos, 0);
|
||||
float last_key_angle = ReadFloat( *e.mValueAccessor, *e.mValueData, pos - 1, 0);
|
||||
float cur_key_time = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
|
||||
float last_key_time = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos - 1, 0);
|
||||
// no more keys on any channel after the current time -> we're done
|
||||
if( nextTime > 1e19)
|
||||
break;
|
||||
|
||||
float last_eval_angle = last_key_angle + (cur_key_angle - last_key_angle) * (time - last_key_time) / (cur_key_time - last_key_time);
|
||||
float delta = std::fabs(cur_key_angle-last_eval_angle);
|
||||
if (delta >= 180.0f) {
|
||||
int subSampleCount = static_cast<int>(std::floorf(delta / 90.0f));
|
||||
if (cur_key_time != time) {
|
||||
float nextSampleTime = time + (cur_key_time - time) / subSampleCount;
|
||||
nextTime = std::min( nextTime, nextSampleTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no more keys on any channel after the current time -> we're done
|
||||
if( nextTime > 1e19)
|
||||
break;
|
||||
|
||||
// else construct next keyframe at this following time point
|
||||
time = nextTime;
|
||||
}
|
||||
}
|
||||
// else construct next keyframe at this following time point
|
||||
time = nextTime;
|
||||
}
|
||||
}
|
||||
|
||||
// there should be some keyframes, but we aren't that fixated on valid input data
|
||||
// ai_assert( resultTrafos.size() > 0);
|
||||
// ai_assert( resultTrafos.size() > 0);
|
||||
|
||||
// build an animation channel for the given node out of these trafo keys
|
||||
if( !resultTrafos.empty() )
|
||||
{
|
||||
aiNodeAnim* dstAnim = new aiNodeAnim;
|
||||
dstAnim->mNodeName = nodeName;
|
||||
dstAnim->mNumPositionKeys = resultTrafos.size();
|
||||
dstAnim->mNumRotationKeys= resultTrafos.size();
|
||||
dstAnim->mNumScalingKeys = resultTrafos.size();
|
||||
dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
|
||||
dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
|
||||
dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
|
||||
if( !resultTrafos.empty() )
|
||||
{
|
||||
aiNodeAnim* dstAnim = new aiNodeAnim;
|
||||
dstAnim->mNodeName = nodeName;
|
||||
dstAnim->mNumPositionKeys = resultTrafos.size();
|
||||
dstAnim->mNumRotationKeys= resultTrafos.size();
|
||||
dstAnim->mNumScalingKeys = resultTrafos.size();
|
||||
dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
|
||||
dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
|
||||
dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
|
||||
|
||||
for( size_t a = 0; a < resultTrafos.size(); ++a)
|
||||
{
|
||||
aiMatrix4x4 mat = resultTrafos[a];
|
||||
double time = double( mat.d4); // remember? time is stored in mat.d4
|
||||
mat.d4 = 1.0f;
|
||||
for( size_t a = 0; a < resultTrafos.size(); ++a)
|
||||
{
|
||||
aiMatrix4x4 mat = resultTrafos[a];
|
||||
double time = double( mat.d4); // remember? time is stored in mat.d4
|
||||
mat.d4 = 1.0f;
|
||||
|
||||
dstAnim->mPositionKeys[a].mTime = time;
|
||||
dstAnim->mRotationKeys[a].mTime = time;
|
||||
dstAnim->mScalingKeys[a].mTime = time;
|
||||
mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
|
||||
}
|
||||
dstAnim->mPositionKeys[a].mTime = time;
|
||||
dstAnim->mRotationKeys[a].mTime = time;
|
||||
dstAnim->mScalingKeys[a].mTime = time;
|
||||
mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
|
||||
}
|
||||
|
||||
anims.push_back( dstAnim);
|
||||
} else
|
||||
{
|
||||
DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
||||
}
|
||||
anims.push_back( dstAnim);
|
||||
} else
|
||||
{
|
||||
DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
||||
}
|
||||
}
|
||||
|
||||
if( !anims.empty())
|
||||
|
@ -1230,9 +1210,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Add a texture to a material structure
|
||||
void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
|
||||
const Collada::Effect& effect,
|
||||
const Collada::Sampler& sampler,
|
||||
aiTextureType type, unsigned int idx)
|
||||
const Collada::Effect& effect,
|
||||
const Collada::Sampler& sampler,
|
||||
aiTextureType type, unsigned int idx)
|
||||
{
|
||||
// first of all, basic file name
|
||||
const aiString name = FindFilenameForEffectTexture( pParser, effect, sampler.mName );
|
||||
|
@ -1359,8 +1339,8 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
|
|||
|
||||
// add textures, if given
|
||||
if( !effect.mTexAmbient.mName.empty())
|
||||
/* It is merely a lightmap */
|
||||
AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
|
||||
/* It is merely a lightmap */
|
||||
AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
|
||||
|
||||
if( !effect.mTexEmissive.mName.empty())
|
||||
AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE);
|
||||
|
@ -1399,7 +1379,7 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
|
|||
|
||||
// create material
|
||||
aiMaterial* mat = new aiMaterial;
|
||||
aiString name( matIt->first);
|
||||
aiString name( material.mName.empty() ? matIt->first : material.mName );
|
||||
mat->AddProperty(&name,AI_MATKEY_NAME);
|
||||
|
||||
// store the material
|
||||
|
@ -1431,7 +1411,7 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Resolves the texture name for the given effect texture entry
|
||||
aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
|
||||
const Collada::Effect& pEffect, const std::string& pName)
|
||||
const Collada::Effect& pEffect, const std::string& pName)
|
||||
{
|
||||
// recurse through the param references until we end up at an image
|
||||
std::string name = pName;
|
||||
|
@ -1508,35 +1488,35 @@ void ColladaLoader::ConvertPath (aiString& ss)
|
|||
ss.data[ss.length] = '\0';
|
||||
}
|
||||
|
||||
// Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
|
||||
// I need to filter it without destroying linux paths starting with "/somewhere"
|
||||
if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
|
||||
{
|
||||
ss.length--;
|
||||
memmove( ss.data, ss.data+1, ss.length);
|
||||
ss.data[ss.length] = 0;
|
||||
}
|
||||
// Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
|
||||
// I need to filter it without destroying linux paths starting with "/somewhere"
|
||||
if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
|
||||
{
|
||||
ss.length--;
|
||||
memmove( ss.data, ss.data+1, ss.length);
|
||||
ss.data[ss.length] = 0;
|
||||
}
|
||||
|
||||
// find and convert all %xy special chars
|
||||
char* out = ss.data;
|
||||
for( const char* it = ss.data; it != ss.data + ss.length; /**/ )
|
||||
{
|
||||
if( *it == '%' && (it + 3) < ss.data + ss.length )
|
||||
{
|
||||
// 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);
|
||||
} else
|
||||
{
|
||||
*out++ = *it++;
|
||||
}
|
||||
}
|
||||
// find and convert all %xy special chars
|
||||
char* out = ss.data;
|
||||
for( const char* it = ss.data; it != ss.data + ss.length; /**/ )
|
||||
{
|
||||
if( *it == '%' && (it + 3) < ss.data + ss.length )
|
||||
{
|
||||
// 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);
|
||||
} else
|
||||
{
|
||||
*out++ = *it++;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust length and terminator of the shortened string
|
||||
*out = 0;
|
||||
ss.length = (ptrdiff_t) (out - ss.data);
|
||||
// adjust length and terminator of the shortened string
|
||||
*out = 0;
|
||||
ss.length = (ptrdiff_t) (out - ss.data);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -1589,17 +1569,17 @@ const Collada::Node* ColladaLoader::FindNode( const Collada::Node* pNode, const
|
|||
// Finds a node in the collada scene by the given SID
|
||||
const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const
|
||||
{
|
||||
if( pNode->mSID == pSID)
|
||||
return pNode;
|
||||
if( pNode->mSID == pSID)
|
||||
return pNode;
|
||||
|
||||
for( size_t a = 0; a < pNode->mChildren.size(); ++a)
|
||||
{
|
||||
const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID);
|
||||
if( node)
|
||||
return node;
|
||||
}
|
||||
for( size_t a = 0; a < pNode->mChildren.size(); ++a)
|
||||
{
|
||||
const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID);
|
||||
if( node)
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -1613,12 +1593,12 @@ std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
|
|||
else if (!pNode->mID.empty())
|
||||
return pNode->mID;
|
||||
else if (!pNode->mSID.empty())
|
||||
return pNode->mSID;
|
||||
else
|
||||
return pNode->mSID;
|
||||
else
|
||||
{
|
||||
// No need to worry. Unnamed nodes are no problem at all, except
|
||||
// if cameras or lights need to be assigned to them.
|
||||
return boost::str( boost::format( "$ColladaAutoName$_%d") % mNodeNameCounter++);
|
||||
return boost::str( boost::format( "$ColladaAutoName$_%d") % mNodeNameCounter++);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
|
|||
{
|
||||
mRootNode = NULL;
|
||||
mUnitSize = 1.0f;
|
||||
mUpDirection = UP_Z;
|
||||
mUpDirection = UP_Y;
|
||||
|
||||
// We assume the newest file format by default
|
||||
mFormat = FV_1_5_n;
|
||||
|
@ -225,10 +225,10 @@ void ColladaParser::ReadAssetInfo()
|
|||
const char* content = GetTextContent();
|
||||
if( strncmp( content, "X_UP", 4) == 0)
|
||||
mUpDirection = UP_X;
|
||||
else if( strncmp( content, "Y_UP", 4) == 0)
|
||||
mUpDirection = UP_Y;
|
||||
else
|
||||
else if( strncmp( content, "Z_UP", 4) == 0)
|
||||
mUpDirection = UP_Z;
|
||||
else
|
||||
mUpDirection = UP_Y;
|
||||
|
||||
// check element end
|
||||
TestClosing( "up_axis");
|
||||
|
@ -817,6 +817,7 @@ void ColladaParser::ReadMaterialLibrary()
|
|||
if( mReader->isEmptyElement())
|
||||
return;
|
||||
|
||||
std::map<std::string, int> names;
|
||||
while( mReader->read())
|
||||
{
|
||||
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
|
||||
|
@ -827,8 +828,32 @@ void ColladaParser::ReadMaterialLibrary()
|
|||
int attrID = GetAttribute( "id");
|
||||
std::string id = mReader->getAttributeValue( attrID);
|
||||
|
||||
std::string name;
|
||||
int attrName = TestAttribute("name");
|
||||
if (attrName >= 0)
|
||||
name = mReader->getAttributeValue( attrName);
|
||||
|
||||
// create an entry and store it in the library under its ID
|
||||
ReadMaterial(mMaterialLibrary[id] = Material());
|
||||
mMaterialLibrary[id] = Material();
|
||||
|
||||
if( !name.empty())
|
||||
{
|
||||
std::map<std::string, int>::iterator it = names.find( name);
|
||||
if( it != names.end())
|
||||
{
|
||||
std::ostringstream strStream;
|
||||
strStream << ++it->second;
|
||||
name.append( " " + strStream.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
names[name] = 0;
|
||||
}
|
||||
|
||||
mMaterialLibrary[id].mName = name;
|
||||
}
|
||||
|
||||
ReadMaterial( mMaterialLibrary[id]);
|
||||
} else
|
||||
{
|
||||
// ignore the rest
|
||||
|
@ -1385,6 +1410,9 @@ void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler)
|
|||
if( attrTex >= 0 )
|
||||
pSampler.mUVChannel = mReader->getAttributeValue( attrTex);
|
||||
//SkipElement();
|
||||
|
||||
// as we've read texture, the color needs to be 1,1,1,1
|
||||
pColor = aiColor4D(1.f, 1.f, 1.f, 1.f);
|
||||
}
|
||||
else if( IsElement( "technique"))
|
||||
{
|
||||
|
@ -1936,6 +1964,10 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
|||
// now here the actual fun starts - these are the indices to construct the mesh data from
|
||||
actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType);
|
||||
}
|
||||
}
|
||||
else if (IsElement("extra"))
|
||||
{
|
||||
SkipElement("extra");
|
||||
} else
|
||||
{
|
||||
ThrowException( boost::str( boost::format( "Unexpected sub element <%s> in tag <%s>") % mReader->getNodeName() % elementName));
|
||||
|
@ -2661,7 +2693,7 @@ void ColladaParser::ReadScene()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Aborts the file reading with an exception
|
||||
void ColladaParser::ThrowException( const std::string& pError) const
|
||||
AI_WONT_RETURN void ColladaParser::ThrowException( const std::string& pError) const
|
||||
{
|
||||
throw DeadlyImportError( boost::str( boost::format( "Collada: %s - %s") % mFileName % pError));
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ protected:
|
|||
|
||||
protected:
|
||||
/** Aborts the file reading with an exception */
|
||||
void ThrowException( const std::string& pError) const;
|
||||
AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
/** Skips all data until the end node of the current element */
|
||||
void SkipElement();
|
||||
|
|
|
@ -454,7 +454,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
|
|||
for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
|
||||
{
|
||||
aiMesh* mesh = pScene->mMeshes[m];
|
||||
unsigned int outIdx;
|
||||
unsigned int outIdx = 0;
|
||||
if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
|
||||
!mesh->mNumVertices)
|
||||
{
|
||||
|
|
|
@ -78,7 +78,8 @@ namespace {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
|
||||
void TokenizeError(const std::string& message, unsigned int offset)
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset)
|
||||
{
|
||||
throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
|
||||
}
|
||||
|
|
|
@ -1256,8 +1256,11 @@ private:
|
|||
// taking notes so we don't need to do it twice.
|
||||
BOOST_FOREACH(WeightIndexArray::value_type index, indices) {
|
||||
|
||||
unsigned int count;
|
||||
unsigned int count = 0;
|
||||
const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count);
|
||||
// ToOutputVertexIndex only returns NULL if index is out of bounds
|
||||
// which should never happen
|
||||
ai_assert(out_idx != NULL);
|
||||
|
||||
index_out_indices.push_back(no_index_sentinel);
|
||||
count_out_indices.push_back(0);
|
||||
|
|
|
@ -242,20 +242,20 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0));
|
||||
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0));
|
||||
fbx_simple_property(InterestPosition, aiVector3D, aiVector3D(0,0,0));
|
||||
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
|
||||
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
|
||||
fbx_simple_property(InterestPosition, aiVector3D, aiVector3D(0,0,0))
|
||||
|
||||
fbx_simple_property(AspectWidth, float, 1.0f);
|
||||
fbx_simple_property(AspectHeight, float, 1.0f);
|
||||
fbx_simple_property(FilmWidth, float, 1.0f);
|
||||
fbx_simple_property(FilmHeight, float, 1.0f);
|
||||
fbx_simple_property(AspectWidth, float, 1.0f)
|
||||
fbx_simple_property(AspectHeight, float, 1.0f)
|
||||
fbx_simple_property(FilmWidth, float, 1.0f)
|
||||
fbx_simple_property(FilmHeight, float, 1.0f)
|
||||
|
||||
fbx_simple_property(FilmAspectRatio, float, 1.0f);
|
||||
fbx_simple_property(ApertureMode, int, 0);
|
||||
fbx_simple_property(FilmAspectRatio, float, 1.0f)
|
||||
fbx_simple_property(ApertureMode, int, 0)
|
||||
|
||||
fbx_simple_property(FieldOfView, float, 1.0f);
|
||||
fbx_simple_property(FocalLength, float, 1.0f);
|
||||
fbx_simple_property(FieldOfView, float, 1.0f)
|
||||
fbx_simple_property(FocalLength, float, 1.0f)
|
||||
|
||||
private:
|
||||
};
|
||||
|
@ -314,37 +314,37 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1));
|
||||
fbx_simple_enum_property(LightType, Type, 0);
|
||||
fbx_simple_property(CastLightOnObject, bool, false);
|
||||
fbx_simple_property(DrawVolumetricLight, bool, true);
|
||||
fbx_simple_property(DrawGroundProjection, bool, true);
|
||||
fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false);
|
||||
fbx_simple_property(Intensity, float, 1.0f);
|
||||
fbx_simple_property(InnerAngle, float, 0.0f);
|
||||
fbx_simple_property(OuterAngle, float, 45.0f);
|
||||
fbx_simple_property(Fog, int, 50);
|
||||
fbx_simple_enum_property(DecayType, Decay, 0);
|
||||
fbx_simple_property(DecayStart, int, 0);
|
||||
fbx_simple_property(FileName, std::string, "");
|
||||
fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1))
|
||||
fbx_simple_enum_property(LightType, Type, 0)
|
||||
fbx_simple_property(CastLightOnObject, bool, false)
|
||||
fbx_simple_property(DrawVolumetricLight, bool, true)
|
||||
fbx_simple_property(DrawGroundProjection, bool, true)
|
||||
fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false)
|
||||
fbx_simple_property(Intensity, float, 1.0f)
|
||||
fbx_simple_property(InnerAngle, float, 0.0f)
|
||||
fbx_simple_property(OuterAngle, float, 45.0f)
|
||||
fbx_simple_property(Fog, int, 50)
|
||||
fbx_simple_enum_property(DecayType, Decay, 0)
|
||||
fbx_simple_property(DecayStart, int, 0)
|
||||
fbx_simple_property(FileName, std::string, "")
|
||||
|
||||
fbx_simple_property(EnableNearAttenuation, bool, false);
|
||||
fbx_simple_property(NearAttenuationStart, float, 0.0f);
|
||||
fbx_simple_property(NearAttenuationEnd, float, 0.0f);
|
||||
fbx_simple_property(EnableFarAttenuation, bool, false);
|
||||
fbx_simple_property(FarAttenuationStart, float, 0.0f);
|
||||
fbx_simple_property(FarAttenuationEnd, float, 0.0f);
|
||||
fbx_simple_property(EnableNearAttenuation, bool, false)
|
||||
fbx_simple_property(NearAttenuationStart, float, 0.0f)
|
||||
fbx_simple_property(NearAttenuationEnd, float, 0.0f)
|
||||
fbx_simple_property(EnableFarAttenuation, bool, false)
|
||||
fbx_simple_property(FarAttenuationStart, float, 0.0f)
|
||||
fbx_simple_property(FarAttenuationEnd, float, 0.0f)
|
||||
|
||||
fbx_simple_property(CastShadows, bool, true);
|
||||
fbx_simple_property(ShadowColor, aiVector3D, aiVector3D(0,0,0));
|
||||
fbx_simple_property(CastShadows, bool, true)
|
||||
fbx_simple_property(ShadowColor, aiVector3D, aiVector3D(0,0,0))
|
||||
|
||||
fbx_simple_property(AreaLightShape, int, 0);
|
||||
fbx_simple_property(AreaLightShape, int, 0)
|
||||
|
||||
fbx_simple_property(LeftBarnDoor, float, 20.0f);
|
||||
fbx_simple_property(RightBarnDoor, float, 20.0f);
|
||||
fbx_simple_property(TopBarnDoor, float, 20.0f);
|
||||
fbx_simple_property(BottomBarnDoor, float, 20.0f);
|
||||
fbx_simple_property(EnableBarnDoor, bool, true);
|
||||
fbx_simple_property(LeftBarnDoor, float, 20.0f)
|
||||
fbx_simple_property(RightBarnDoor, float, 20.0f)
|
||||
fbx_simple_property(TopBarnDoor, float, 20.0f)
|
||||
fbx_simple_property(BottomBarnDoor, float, 20.0f)
|
||||
fbx_simple_property(EnableBarnDoor, bool, true)
|
||||
|
||||
|
||||
private:
|
||||
|
@ -387,81 +387,81 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
fbx_simple_property(QuaternionInterpolate, int, 0);
|
||||
fbx_simple_property(QuaternionInterpolate, int, 0)
|
||||
|
||||
fbx_simple_property(RotationOffset, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(RotationPivot, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(ScalingOffset, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(ScalingPivot, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(TranslationActive, bool, false);
|
||||
fbx_simple_property(RotationOffset, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(RotationPivot, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(ScalingOffset, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(ScalingPivot, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(TranslationActive, bool, false)
|
||||
|
||||
fbx_simple_property(TranslationMin, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(TranslationMax, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(TranslationMin, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(TranslationMax, aiVector3D, aiVector3D())
|
||||
|
||||
fbx_simple_property(TranslationMinX, bool, false);
|
||||
fbx_simple_property(TranslationMaxX, bool, false);
|
||||
fbx_simple_property(TranslationMinY, bool, false);
|
||||
fbx_simple_property(TranslationMaxY, bool, false);
|
||||
fbx_simple_property(TranslationMinZ, bool, false);
|
||||
fbx_simple_property(TranslationMaxZ, bool, false);
|
||||
fbx_simple_property(TranslationMinX, bool, false)
|
||||
fbx_simple_property(TranslationMaxX, bool, false)
|
||||
fbx_simple_property(TranslationMinY, bool, false)
|
||||
fbx_simple_property(TranslationMaxY, bool, false)
|
||||
fbx_simple_property(TranslationMinZ, bool, false)
|
||||
fbx_simple_property(TranslationMaxZ, bool, false)
|
||||
|
||||
fbx_simple_enum_property(RotationOrder, RotOrder, 0);
|
||||
fbx_simple_property(RotationSpaceForLimitOnly, bool, false);
|
||||
fbx_simple_property(RotationStiffnessX, float, 0.0f);
|
||||
fbx_simple_property(RotationStiffnessY, float, 0.0f);
|
||||
fbx_simple_property(RotationStiffnessZ, float, 0.0f);
|
||||
fbx_simple_property(AxisLen, float, 0.0f);
|
||||
fbx_simple_enum_property(RotationOrder, RotOrder, 0)
|
||||
fbx_simple_property(RotationSpaceForLimitOnly, bool, false)
|
||||
fbx_simple_property(RotationStiffnessX, float, 0.0f)
|
||||
fbx_simple_property(RotationStiffnessY, float, 0.0f)
|
||||
fbx_simple_property(RotationStiffnessZ, float, 0.0f)
|
||||
fbx_simple_property(AxisLen, float, 0.0f)
|
||||
|
||||
fbx_simple_property(PreRotation, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(PostRotation, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(RotationActive, bool, false);
|
||||
fbx_simple_property(PreRotation, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(PostRotation, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(RotationActive, bool, false)
|
||||
|
||||
fbx_simple_property(RotationMin, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(RotationMax, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(RotationMin, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(RotationMax, aiVector3D, aiVector3D())
|
||||
|
||||
fbx_simple_property(RotationMinX, bool, false);
|
||||
fbx_simple_property(RotationMaxX, bool, false);
|
||||
fbx_simple_property(RotationMinY, bool, false);
|
||||
fbx_simple_property(RotationMaxY, bool, false);
|
||||
fbx_simple_property(RotationMinZ, bool, false);
|
||||
fbx_simple_property(RotationMaxZ, bool, false);
|
||||
fbx_simple_enum_property(InheritType, TransformInheritance, 0);
|
||||
fbx_simple_property(RotationMinX, bool, false)
|
||||
fbx_simple_property(RotationMaxX, bool, false)
|
||||
fbx_simple_property(RotationMinY, bool, false)
|
||||
fbx_simple_property(RotationMaxY, bool, false)
|
||||
fbx_simple_property(RotationMinZ, bool, false)
|
||||
fbx_simple_property(RotationMaxZ, bool, false)
|
||||
fbx_simple_enum_property(InheritType, TransformInheritance, 0)
|
||||
|
||||
fbx_simple_property(ScalingActive, bool, false);
|
||||
fbx_simple_property(ScalingMin, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(ScalingMax, aiVector3D, aiVector3D(1.f,1.f,1.f));
|
||||
fbx_simple_property(ScalingMinX, bool, false);
|
||||
fbx_simple_property(ScalingMaxX, bool, false);
|
||||
fbx_simple_property(ScalingMinY, bool, false);
|
||||
fbx_simple_property(ScalingMaxY, bool, false);
|
||||
fbx_simple_property(ScalingMinZ, bool, false);
|
||||
fbx_simple_property(ScalingMaxZ, bool, false);
|
||||
fbx_simple_property(ScalingActive, bool, false)
|
||||
fbx_simple_property(ScalingMin, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(ScalingMax, aiVector3D, aiVector3D(1.f,1.f,1.f))
|
||||
fbx_simple_property(ScalingMinX, bool, false)
|
||||
fbx_simple_property(ScalingMaxX, bool, false)
|
||||
fbx_simple_property(ScalingMinY, bool, false)
|
||||
fbx_simple_property(ScalingMaxY, bool, false)
|
||||
fbx_simple_property(ScalingMinZ, bool, false)
|
||||
fbx_simple_property(ScalingMaxZ, bool, false)
|
||||
|
||||
fbx_simple_property(GeometricTranslation, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(GeometricRotation, aiVector3D, aiVector3D());
|
||||
fbx_simple_property(GeometricScaling, aiVector3D, aiVector3D(1.f, 1.f, 1.f));
|
||||
fbx_simple_property(GeometricTranslation, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(GeometricRotation, aiVector3D, aiVector3D())
|
||||
fbx_simple_property(GeometricScaling, aiVector3D, aiVector3D(1.f, 1.f, 1.f))
|
||||
|
||||
fbx_simple_property(MinDampRangeX, float, 0.0f);
|
||||
fbx_simple_property(MinDampRangeY, float, 0.0f);
|
||||
fbx_simple_property(MinDampRangeZ, float, 0.0f);
|
||||
fbx_simple_property(MaxDampRangeX, float, 0.0f);
|
||||
fbx_simple_property(MaxDampRangeY, float, 0.0f);
|
||||
fbx_simple_property(MaxDampRangeZ, float, 0.0f);
|
||||
fbx_simple_property(MinDampRangeX, float, 0.0f)
|
||||
fbx_simple_property(MinDampRangeY, float, 0.0f)
|
||||
fbx_simple_property(MinDampRangeZ, float, 0.0f)
|
||||
fbx_simple_property(MaxDampRangeX, float, 0.0f)
|
||||
fbx_simple_property(MaxDampRangeY, float, 0.0f)
|
||||
fbx_simple_property(MaxDampRangeZ, float, 0.0f)
|
||||
|
||||
fbx_simple_property(MinDampStrengthX, float, 0.0f);
|
||||
fbx_simple_property(MinDampStrengthY, float, 0.0f);
|
||||
fbx_simple_property(MinDampStrengthZ, float, 0.0f);
|
||||
fbx_simple_property(MaxDampStrengthX, float, 0.0f);
|
||||
fbx_simple_property(MaxDampStrengthY, float, 0.0f);
|
||||
fbx_simple_property(MaxDampStrengthZ, float, 0.0f);
|
||||
fbx_simple_property(MinDampStrengthX, float, 0.0f)
|
||||
fbx_simple_property(MinDampStrengthY, float, 0.0f)
|
||||
fbx_simple_property(MinDampStrengthZ, float, 0.0f)
|
||||
fbx_simple_property(MaxDampStrengthX, float, 0.0f)
|
||||
fbx_simple_property(MaxDampStrengthY, float, 0.0f)
|
||||
fbx_simple_property(MaxDampStrengthZ, float, 0.0f)
|
||||
|
||||
fbx_simple_property(PreferredAngleX, float, 0.0f);
|
||||
fbx_simple_property(PreferredAngleY, float, 0.0f);
|
||||
fbx_simple_property(PreferredAngleZ, float, 0.0f);
|
||||
fbx_simple_property(PreferredAngleX, float, 0.0f)
|
||||
fbx_simple_property(PreferredAngleY, float, 0.0f)
|
||||
fbx_simple_property(PreferredAngleZ, float, 0.0f)
|
||||
|
||||
fbx_simple_property(Show, bool, true);
|
||||
fbx_simple_property(LODBox, bool, false);
|
||||
fbx_simple_property(Freeze, bool, false);
|
||||
fbx_simple_property(Show, bool, true)
|
||||
fbx_simple_property(LODBox, bool, false)
|
||||
fbx_simple_property(Freeze, bool, false)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -1015,10 +1015,10 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
fbx_simple_property(LocalStart, uint64_t, 0L);
|
||||
fbx_simple_property(LocalStop, uint64_t, 0L);
|
||||
fbx_simple_property(ReferenceStart, uint64_t, 0L);
|
||||
fbx_simple_property(ReferenceStop, uint64_t, 0L);
|
||||
fbx_simple_property(LocalStart, uint64_t, 0L)
|
||||
fbx_simple_property(LocalStop, uint64_t, 0L)
|
||||
fbx_simple_property(ReferenceStart, uint64_t, 0L)
|
||||
fbx_simple_property(ReferenceStop, uint64_t, 0L)
|
||||
|
||||
|
||||
|
||||
|
@ -1227,18 +1227,18 @@ public:
|
|||
}
|
||||
|
||||
|
||||
fbx_simple_property(UpAxis, int, 1);
|
||||
fbx_simple_property(UpAxisSign, int, 1);
|
||||
fbx_simple_property(FrontAxis, int, 2);
|
||||
fbx_simple_property(FrontAxisSign, int, 1);
|
||||
fbx_simple_property(CoordAxis, int, 0);
|
||||
fbx_simple_property(CoordAxisSign, int, 1);
|
||||
fbx_simple_property(OriginalUpAxis, int, 0);
|
||||
fbx_simple_property(OriginalUpAxisSign, int, 1);
|
||||
fbx_simple_property(UnitScaleFactor, double, 1);
|
||||
fbx_simple_property(OriginalUnitScaleFactor, double, 1);
|
||||
fbx_simple_property(AmbientColor, aiVector3D, aiVector3D(0,0,0));
|
||||
fbx_simple_property(DefaultCamera, std::string, "");
|
||||
fbx_simple_property(UpAxis, int, 1)
|
||||
fbx_simple_property(UpAxisSign, int, 1)
|
||||
fbx_simple_property(FrontAxis, int, 2)
|
||||
fbx_simple_property(FrontAxisSign, int, 1)
|
||||
fbx_simple_property(CoordAxis, int, 0)
|
||||
fbx_simple_property(CoordAxisSign, int, 1)
|
||||
fbx_simple_property(OriginalUpAxis, int, 0)
|
||||
fbx_simple_property(OriginalUpAxisSign, int, 1)
|
||||
fbx_simple_property(UnitScaleFactor, double, 1)
|
||||
fbx_simple_property(OriginalUnitScaleFactor, double, 1)
|
||||
fbx_simple_property(AmbientColor, aiVector3D, aiVector3D(0,0,0))
|
||||
fbx_simple_property(DefaultCamera, std::string, "")
|
||||
|
||||
|
||||
enum FrameRate {
|
||||
|
@ -1261,10 +1261,10 @@ public:
|
|||
FrameRate_MAX// end-of-enum sentinel
|
||||
};
|
||||
|
||||
fbx_simple_enum_property(TimeMode, FrameRate, FrameRate_DEFAULT);
|
||||
fbx_simple_property(TimeSpanStart, uint64_t, 0L);
|
||||
fbx_simple_property(TimeSpanStop, uint64_t, 0L);
|
||||
fbx_simple_property(CustomFrameRate, float, -1.0f);
|
||||
fbx_simple_enum_property(TimeMode, FrameRate, FrameRate_DEFAULT)
|
||||
fbx_simple_property(TimeSpanStart, uint64_t, 0L)
|
||||
fbx_simple_property(TimeSpanStop, uint64_t, 0L)
|
||||
fbx_simple_property(CustomFrameRate, float, -1.0f)
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
@ -68,13 +68,15 @@ namespace {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// signal parse error, this is always unrecoverable. Throws DeadlyImportError.
|
||||
void ParseError(const std::string& message, const Token& token)
|
||||
AI_WONT_RETURN void ParseError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void ParseError(const std::string& message, const Token& token)
|
||||
{
|
||||
throw DeadlyImportError(Util::AddTokenText("FBX-Parser",message,&token));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ParseError(const std::string& message, const Element* element = NULL)
|
||||
AI_WONT_RETURN void ParseError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void ParseError(const std::string& message, const Element* element)
|
||||
{
|
||||
if(element) {
|
||||
ParseError(message,element->KeyToken());
|
||||
|
|
|
@ -86,7 +86,8 @@ namespace {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
|
||||
void TokenizeError(const std::string& message, unsigned int line, unsigned int column)
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column)
|
||||
{
|
||||
throw DeadlyImportError(Util::AddLineAndColumn("FBX-Tokenize",message,line,column));
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
|
|||
bool first = true;
|
||||
|
||||
// check whether the face contains degenerated entries
|
||||
for (register unsigned int i = 0; i < face.mNumIndices; ++i)
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
// Polygons with more than 4 points are allowed to have double points, that is
|
||||
// simulating polygons with holes just with concave polygons. However,
|
||||
|
@ -116,7 +116,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
|
|||
if (face.mNumIndices > 4)
|
||||
limit = std::min(limit,i+2);
|
||||
|
||||
for (register unsigned int t = i+1; t < limit; ++t)
|
||||
for (unsigned int t = i+1; t < limit; ++t)
|
||||
{
|
||||
if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]])
|
||||
{
|
||||
|
|
|
@ -89,7 +89,7 @@ void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMap
|
|||
unsigned int out = 0;
|
||||
for (unsigned int a = 0; a < node->mNumMeshes;++a) {
|
||||
|
||||
register unsigned int ref = node->mMeshes[a];
|
||||
unsigned int ref = node->mMeshes[a];
|
||||
if (UINT_MAX != (ref = meshMapping[ref])) {
|
||||
node->mMeshes[out++] = ref;
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
|||
// Write the smoothed normal back to all affected normals
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
||||
{
|
||||
register unsigned int vidx = verticesFound[a];
|
||||
unsigned int vidx = verticesFound[a];
|
||||
pcNew[vidx] = pcNor;
|
||||
abHad[vidx] = true;
|
||||
}
|
||||
|
|
|
@ -50,42 +50,97 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "ProcessHelper.h"
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
namespace IFC {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
enum Intersect {
|
||||
Intersect_No,
|
||||
Intersect_LiesOnPlane,
|
||||
Intersect_Yes
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const IfcVector3& e0,
|
||||
const IfcVector3& e1,
|
||||
IfcVector3& out)
|
||||
// Calculates intersection between line segment and plane. To catch corner cases, specify which side you prefer.
|
||||
// The function then generates a hit only if the end is beyond a certain margin in that direction, filtering out
|
||||
// "very close to plane" ghost hits as long as start and end stay directly on or within the given plane side.
|
||||
bool IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const IfcVector3& e0,
|
||||
const IfcVector3& e1, bool assumeStartOnWhiteSide, IfcVector3& out)
|
||||
{
|
||||
const IfcVector3 pdelta = e0 - p, seg = e1-e0;
|
||||
const IfcVector3 pdelta = e0 - p, seg = e1 - e0;
|
||||
const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta);
|
||||
|
||||
if (std::fabs(dotOne) < 1e-6) {
|
||||
return std::fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
|
||||
// if segment ends on plane, do not report a hit. We stay on that side until a following segment starting at this
|
||||
// point leaves the plane through the other side
|
||||
if( std::abs(dotOne + dotTwo) < 1e-6 )
|
||||
return false;
|
||||
|
||||
// if segment starts on the plane, report a hit only if the end lies on the *other* side
|
||||
if( std::abs(dotTwo) < 1e-6 )
|
||||
{
|
||||
if( (assumeStartOnWhiteSide && dotOne + dotTwo < 1e-6) || (!assumeStartOnWhiteSide && dotOne + dotTwo > -1e-6) )
|
||||
{
|
||||
out = e0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const IfcFloat t = dotTwo/dotOne;
|
||||
// ignore if segment is parallel to plane and far away from it on either side
|
||||
// Warning: if there's a few thousand of such segments which slowly accumulate beyond the epsilon, no hit would be registered
|
||||
if( std::abs(dotOne) < 1e-6 )
|
||||
return false;
|
||||
|
||||
// t must be in [0..1] if the intersection point is within the given segment
|
||||
if (t > 1.f || t < 0.f) {
|
||||
return Intersect_No;
|
||||
}
|
||||
out = e0+t*seg;
|
||||
return Intersect_Yes;
|
||||
const IfcFloat t = dotTwo / dotOne;
|
||||
if( t > 1.0 || t < 0.0 )
|
||||
return false;
|
||||
|
||||
out = e0 + t*seg;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void FilterPolygon(std::vector<IfcVector3>& resultpoly)
|
||||
{
|
||||
if( resultpoly.size() < 3 )
|
||||
{
|
||||
resultpoly.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
IfcVector3 vmin, vmax;
|
||||
ArrayBounds(resultpoly.data(), resultpoly.size(), vmin, vmax);
|
||||
|
||||
// filter our IfcFloat points - those may happen if a point lies
|
||||
// directly on the intersection line or directly on the clipping plane
|
||||
const IfcFloat epsilon = (vmax - vmin).SquareLength() / 1e6f;
|
||||
FuzzyVectorCompare fz(epsilon);
|
||||
std::vector<IfcVector3>::iterator e = std::unique(resultpoly.begin(), resultpoly.end(), fz);
|
||||
|
||||
if( e != resultpoly.end() )
|
||||
resultpoly.erase(e, resultpoly.end());
|
||||
|
||||
if( !resultpoly.empty() && fz(resultpoly.front(), resultpoly.back()) )
|
||||
resultpoly.pop_back();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void WritePolygon(std::vector<IfcVector3>& resultpoly, TempMesh& result)
|
||||
{
|
||||
FilterPolygon(resultpoly);
|
||||
|
||||
if( resultpoly.size() > 2 )
|
||||
{
|
||||
result.verts.insert(result.verts.end(), resultpoly.begin(), resultpoly.end());
|
||||
result.vertcnt.push_back(resultpoly.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
|
||||
const TempMesh& first_operand,
|
||||
ConversionData& /*conv*/)
|
||||
const TempMesh& first_operand,
|
||||
ConversionData& /*conv*/)
|
||||
{
|
||||
ai_assert(hs != NULL);
|
||||
|
||||
|
@ -120,20 +175,14 @@ void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& re
|
|||
for(iit = begin; iit != end; vidx += *iit++) {
|
||||
|
||||
unsigned int newcount = 0;
|
||||
for(unsigned int i = 0; i < *iit; ++i) {
|
||||
const IfcVector3& e0 = in[vidx+i], e1 = in[vidx+(i+1)%*iit];
|
||||
bool isAtWhiteSide = (in[vidx] - p) * n > -1e-6;
|
||||
for( unsigned int i = 0; i < *iit; ++i ) {
|
||||
const IfcVector3& e0 = in[vidx + i], e1 = in[vidx + (i + 1) % *iit];
|
||||
|
||||
// does the next segment intersect the plane?
|
||||
IfcVector3 isectpos;
|
||||
const Intersect isect = IntersectSegmentPlane(p,n,e0,e1,isectpos);
|
||||
if (isect == Intersect_No || isect == Intersect_LiesOnPlane) {
|
||||
if ( (e0-p).Normalize()*n > 0 ) {
|
||||
outvert.push_back(e0);
|
||||
++newcount;
|
||||
}
|
||||
}
|
||||
else if (isect == Intersect_Yes) {
|
||||
if ( (e0-p).Normalize()*n > 0 ) {
|
||||
if( IntersectSegmentPlane(p, n, e0, e1, isAtWhiteSide, isectpos) ) {
|
||||
if( isAtWhiteSide ) {
|
||||
// e0 is on the right side, so keep it
|
||||
outvert.push_back(e0);
|
||||
outvert.push_back(isectpos);
|
||||
|
@ -144,6 +193,14 @@ void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& re
|
|||
outvert.push_back(isectpos);
|
||||
++newcount;
|
||||
}
|
||||
isAtWhiteSide = !isAtWhiteSide;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( isAtWhiteSide ) {
|
||||
outvert.push_back(e0);
|
||||
++newcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,76 +242,114 @@ void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& re
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Check if e0-e1 intersects a sub-segment of the given boundary line.
|
||||
// note: this functions works on 3D vectors, but performs its intersection checks solely in xy.
|
||||
bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, const std::vector<IfcVector3>& boundary,
|
||||
std::vector<size_t>& intersected_boundary_segments,
|
||||
std::vector<IfcVector3>& intersected_boundary_points,
|
||||
bool half_open = false,
|
||||
bool* e0_hits_border = NULL)
|
||||
// New version takes the supposed inside/outside state as a parameter and treats corner cases as if
|
||||
// the line stays on that side. This should make corner cases more stable.
|
||||
// Two million assumptions! Boundary should have all z at 0.0, will be treated as closed, should not have
|
||||
// segments with length <1e-6, self-intersecting might break the corner case handling... just don't go there, ok?
|
||||
bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const std::vector<IfcVector3>& boundary,
|
||||
const bool isStartAssumedInside, std::vector<std::pair<size_t, IfcVector3> >& intersect_results,
|
||||
const bool halfOpen = false)
|
||||
{
|
||||
ai_assert(intersected_boundary_segments.empty());
|
||||
ai_assert(intersected_boundary_points.empty());
|
||||
ai_assert(intersect_results.empty());
|
||||
|
||||
if(e0_hits_border) {
|
||||
*e0_hits_border = false;
|
||||
// determine winding order - necessary to detect segments going "inwards" or "outwards" from a point directly on the border
|
||||
// positive sum of angles means clockwise order when looking down the -Z axis
|
||||
IfcFloat windingOrder = 0.0;
|
||||
for( size_t i = 0, bcount = boundary.size(); i < bcount; ++i ) {
|
||||
IfcVector3 b01 = boundary[(i + 1) % bcount] - boundary[i];
|
||||
IfcVector3 b12 = boundary[(i + 2) % bcount] - boundary[(i + 1) % bcount];
|
||||
IfcVector3 b1_side = IfcVector3(b01.y, -b01.x, 0.0); // rotated 90° clockwise in Z plane
|
||||
// Warning: rough estimate only. A concave poly with lots of small segments each featuring a small counter rotation
|
||||
// could fool the accumulation. Correct implementation would be sum( acos( b01 * b2) * sign( b12 * b1_side))
|
||||
windingOrder += (b1_side.x*b12.x + b1_side.y*b12.y);
|
||||
}
|
||||
windingOrder = windingOrder > 0.0 ? 1.0 : -1.0;
|
||||
|
||||
const IfcVector3& e = e1 - e0;
|
||||
const IfcVector3 e = e1 - e0;
|
||||
|
||||
for (size_t i = 0, bcount = boundary.size(); i < bcount; ++i) {
|
||||
for( size_t i = 0, bcount = boundary.size(); i < bcount; ++i ) {
|
||||
// boundary segment i: b0-b1
|
||||
const IfcVector3& b0 = boundary[i];
|
||||
const IfcVector3& b1 = boundary[(i+1) % bcount];
|
||||
|
||||
const IfcVector3& b = b1 - b0;
|
||||
const IfcVector3& b1 = boundary[(i + 1) % bcount];
|
||||
IfcVector3 b = b1 - b0;
|
||||
IfcFloat b_sqlen_inv = 1.0 / b.SquareLength();
|
||||
|
||||
// segment-segment intersection
|
||||
// solve b0 + b*s = e0 + e*t for (s,t)
|
||||
const IfcFloat det = (-b.x * e.y + e.x * b.y);
|
||||
if(std::fabs(det) < 1e-6) {
|
||||
if( std::abs(det) < 1e-6 ) {
|
||||
// no solutions (parallel lines)
|
||||
continue;
|
||||
}
|
||||
|
||||
const IfcFloat x = b0.x - e0.x;
|
||||
const IfcFloat y = b0.y - e0.y;
|
||||
|
||||
const IfcFloat s = (x*e.y - e.x*y)/det;
|
||||
const IfcFloat t = (x*b.y - b.x*y)/det;
|
||||
|
||||
const IfcFloat s = (x*e.y - e.x*y) / det; // scale along boundary edge
|
||||
const IfcFloat t = (x*b.y - b.x*y) / det; // scale along given segment
|
||||
const IfcVector3 p = e0 + e*t;
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
const IfcVector3 check = b0 + b*s - (e0 + e*t);
|
||||
ai_assert((IfcVector2(check.x,check.y)).SquareLength() < 1e-5);
|
||||
const IfcVector3 check = b0 + b*s - p;
|
||||
ai_assert((IfcVector2(check.x, check.y)).SquareLength() < 1e-5);
|
||||
#endif
|
||||
|
||||
// for a valid intersection, s-t should be in range [0,1].
|
||||
// note that for t (i.e. the segment point) we only use a
|
||||
// half-sided epsilon because the next segment should catch
|
||||
// this case.
|
||||
const IfcFloat epsilon = 1e-6;
|
||||
if (t >= -epsilon && (t <= 1.0+epsilon || half_open) && s >= -epsilon && s <= 1.0) {
|
||||
// also calculate the distance of e0 and e1 to the segment. We need to detect the "starts directly on segment"
|
||||
// and "ends directly at segment" cases
|
||||
bool startsAtSegment, endsAtSegment;
|
||||
{
|
||||
// calculate closest point to each end on the segment, clamp that point to the segment's length, then check
|
||||
// distance to that point. This approach is like testing if e0 is inside a capped cylinder.
|
||||
IfcFloat et0 = (b.x*(e0.x - b0.x) + b.y*(e0.y - b0.y)) * b_sqlen_inv;
|
||||
IfcVector3 closestPosToE0OnBoundary = b0 + std::max(IfcFloat(0.0), std::min(IfcFloat(1.0), et0)) * b;
|
||||
startsAtSegment = (closestPosToE0OnBoundary - IfcVector3(e0.x, e0.y, 0.0)).SquareLength() < 1e-12;
|
||||
IfcFloat et1 = (b.x*(e1.x - b0.x) + b.y*(e1.y - b0.y)) * b_sqlen_inv;
|
||||
IfcVector3 closestPosToE1OnBoundary = b0 + std::max(IfcFloat(0.0), std::min(IfcFloat(1.0), et1)) * b;
|
||||
endsAtSegment = (closestPosToE1OnBoundary - IfcVector3(e1.x, e1.y, 0.0)).SquareLength() < 1e-12;
|
||||
}
|
||||
|
||||
if (e0_hits_border && !*e0_hits_border) {
|
||||
*e0_hits_border = std::fabs(t) < 1e-5f;
|
||||
}
|
||||
// Line segment ends at boundary -> ignore any hit, it will be handled by possibly following segments
|
||||
if( endsAtSegment && !halfOpen )
|
||||
continue;
|
||||
|
||||
const IfcVector3& p = e0 + e*t;
|
||||
// Line segment starts at boundary -> generate a hit only if following that line would change the INSIDE/OUTSIDE
|
||||
// state. This should catch the case where a connected set of segments has a point directly on the boundary,
|
||||
// one segment not hitting it because it ends there and the next segment not hitting it because it starts there
|
||||
// Should NOT generate a hit if the segment only touches the boundary but turns around and stays inside.
|
||||
if( startsAtSegment )
|
||||
{
|
||||
IfcVector3 inside_dir = IfcVector3(b.y, -b.x, 0.0) * windingOrder;
|
||||
bool isGoingInside = (inside_dir * e) > 0.0;
|
||||
if( isGoingInside == isStartAssumedInside )
|
||||
continue;
|
||||
|
||||
// only insert the point into the list if it is sufficiently
|
||||
// far away from the previous intersection point. This way,
|
||||
// we avoid duplicate detection if the intersection is
|
||||
// directly on the vertex between two segments.
|
||||
if (!intersected_boundary_points.empty() && intersected_boundary_segments.back()==i-1 ) {
|
||||
const IfcVector3 diff = intersected_boundary_points.back() - p;
|
||||
if(IfcVector2(diff.x, diff.y).SquareLength() < 1e-7) {
|
||||
// only insert the point into the list if it is sufficiently far away from the previous intersection point.
|
||||
// This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments.
|
||||
if( !intersect_results.empty() && intersect_results.back().first == i - 1 )
|
||||
{
|
||||
const IfcVector3 diff = intersect_results.back().second - e0;
|
||||
if( IfcVector2(diff.x, diff.y).SquareLength() < 1e-10 )
|
||||
continue;
|
||||
}
|
||||
}
|
||||
intersected_boundary_segments.push_back(i);
|
||||
intersected_boundary_points.push_back(p);
|
||||
intersect_results.push_back(std::make_pair(i, e0));
|
||||
continue;
|
||||
}
|
||||
|
||||
// for a valid intersection, s and t should be in range [0,1]. Including a bit of epsilon on s, potential double
|
||||
// hits on two consecutive boundary segments are filtered
|
||||
if( s >= -1e-6 * b_sqlen_inv && s <= 1.0 + 1e-6*b_sqlen_inv && t >= 0.0 && (t <= 1.0 || halfOpen) )
|
||||
{
|
||||
// only insert the point into the list if it is sufficiently far away from the previous intersection point.
|
||||
// This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments.
|
||||
if( !intersect_results.empty() && intersect_results.back().first == i - 1 )
|
||||
{
|
||||
const IfcVector3 diff = intersect_results.back().second - p;
|
||||
if( IfcVector2(diff.x, diff.y).SquareLength() < 1e-10 )
|
||||
continue;
|
||||
}
|
||||
intersect_results.push_back(std::make_pair(i, p));
|
||||
}
|
||||
}
|
||||
|
||||
return !intersected_boundary_segments.empty();
|
||||
return !intersect_results.empty();
|
||||
}
|
||||
|
||||
|
||||
|
@ -272,47 +367,21 @@ bool PointInPoly(const IfcVector3& p, const std::vector<IfcVector3>& boundary)
|
|||
// the border of the polygon. If any of our attempts produces this result,
|
||||
// we return false immediately.
|
||||
|
||||
std::vector<size_t> intersected_boundary_segments;
|
||||
std::vector<IfcVector3> intersected_boundary_points;
|
||||
std::vector<std::pair<size_t, IfcVector3> > intersected_boundary;
|
||||
size_t votes = 0;
|
||||
|
||||
bool is_border;
|
||||
IntersectsBoundaryProfile(p, p + IfcVector3(1.0,0,0), boundary,
|
||||
intersected_boundary_segments,
|
||||
intersected_boundary_points, true, &is_border);
|
||||
IntersectsBoundaryProfile(p, p + IfcVector3(1.0, 0, 0), boundary, true, intersected_boundary, true);
|
||||
votes += intersected_boundary.size() % 2;
|
||||
|
||||
if(is_border) {
|
||||
return false;
|
||||
}
|
||||
intersected_boundary.clear();
|
||||
IntersectsBoundaryProfile(p, p + IfcVector3(0, 1.0, 0), boundary, true, intersected_boundary, true);
|
||||
votes += intersected_boundary.size() % 2;
|
||||
|
||||
votes += intersected_boundary_segments.size() % 2;
|
||||
intersected_boundary.clear();
|
||||
IntersectsBoundaryProfile(p, p + IfcVector3(0.6, -0.6, 0.0), boundary, true, intersected_boundary, true);
|
||||
votes += intersected_boundary.size() % 2;
|
||||
|
||||
intersected_boundary_segments.clear();
|
||||
intersected_boundary_points.clear();
|
||||
|
||||
IntersectsBoundaryProfile(p, p + IfcVector3(0,1.0,0), boundary,
|
||||
intersected_boundary_segments,
|
||||
intersected_boundary_points, true, &is_border);
|
||||
|
||||
if(is_border) {
|
||||
return false;
|
||||
}
|
||||
|
||||
votes += intersected_boundary_segments.size() % 2;
|
||||
|
||||
intersected_boundary_segments.clear();
|
||||
intersected_boundary_points.clear();
|
||||
|
||||
IntersectsBoundaryProfile(p, p + IfcVector3(0.6,-0.6,0.0), boundary,
|
||||
intersected_boundary_segments,
|
||||
intersected_boundary_points, true, &is_border);
|
||||
|
||||
if(is_border) {
|
||||
return false;
|
||||
}
|
||||
|
||||
votes += intersected_boundary_segments.size() % 2;
|
||||
//ai_assert(votes == 3 || votes == 0);
|
||||
// ai_assert(votes == 3 || votes == 0);
|
||||
return votes > 1;
|
||||
}
|
||||
|
||||
|
@ -350,6 +419,9 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
|
|||
return;
|
||||
}
|
||||
|
||||
// determine winding order by calculating the normal.
|
||||
IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(profile->verts.data(), profile->verts.size());
|
||||
|
||||
IfcMatrix4 proj_inv;
|
||||
ConvertAxisPlacement(proj_inv,hs->Position);
|
||||
|
||||
|
@ -361,256 +433,287 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
|
|||
// clip the current contents of `meshout` against the plane we obtained from the second operand
|
||||
const std::vector<IfcVector3>& in = first_operand.verts;
|
||||
std::vector<IfcVector3>& outvert = result.verts;
|
||||
|
||||
std::vector<unsigned int>::const_iterator begin = first_operand.vertcnt.begin(),
|
||||
end = first_operand.vertcnt.end(), iit;
|
||||
std::vector<unsigned int>& outvertcnt = result.vertcnt;
|
||||
|
||||
outvert.reserve(in.size());
|
||||
result.vertcnt.reserve(first_operand.vertcnt.size());
|
||||
outvertcnt.reserve(first_operand.vertcnt.size());
|
||||
|
||||
std::vector<size_t> intersected_boundary_segments;
|
||||
std::vector<IfcVector3> intersected_boundary_points;
|
||||
|
||||
// TODO: the following algorithm doesn't handle all cases.
|
||||
unsigned int vidx = 0;
|
||||
for(iit = begin; iit != end; vidx += *iit++) {
|
||||
if (!*iit) {
|
||||
continue;
|
||||
std::vector<unsigned int>::const_iterator begin = first_operand.vertcnt.begin();
|
||||
std::vector<unsigned int>::const_iterator end = first_operand.vertcnt.end();
|
||||
std::vector<unsigned int>::const_iterator iit;
|
||||
for( iit = begin; iit != end; vidx += *iit++ )
|
||||
{
|
||||
// Our new approach: we cut the poly along the plane, then we intersect the part on the black side of the plane
|
||||
// against the bounding polygon. All the white parts, and the black part outside the boundary polygon, are kept.
|
||||
std::vector<IfcVector3> whiteside, blackside;
|
||||
|
||||
{
|
||||
const IfcVector3* srcVertices = &in[vidx];
|
||||
const size_t srcVtxCount = *iit;
|
||||
if( srcVtxCount == 0 )
|
||||
continue;
|
||||
|
||||
IfcVector3 polyNormal = TempMesh::ComputePolygonNormal(srcVertices, srcVtxCount, true);
|
||||
|
||||
// if the poly is parallel to the plane, put it completely on the black or white side
|
||||
if( std::abs(polyNormal * n) > 0.9999 )
|
||||
{
|
||||
bool isOnWhiteSide = (srcVertices[0] - p) * n > -1e-6;
|
||||
std::vector<IfcVector3>& targetSide = isOnWhiteSide ? whiteside : blackside;
|
||||
targetSide.insert(targetSide.end(), srcVertices, srcVertices + srcVtxCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise start building one polygon for each side. Whenever the current line segment intersects the plane
|
||||
// we put a point there as an end of the current segment. Then we switch to the other side, put a point there, too,
|
||||
// as a beginning of the current segment, and simply continue accumulating vertices.
|
||||
bool isCurrentlyOnWhiteSide = ((srcVertices[0]) - p) * n > -1e-6;
|
||||
for( size_t a = 0; a < srcVtxCount; ++a )
|
||||
{
|
||||
IfcVector3 e0 = srcVertices[a];
|
||||
IfcVector3 e1 = srcVertices[(a + 1) % srcVtxCount];
|
||||
IfcVector3 ei;
|
||||
|
||||
// put starting point to the current mesh
|
||||
std::vector<IfcVector3>& trgt = isCurrentlyOnWhiteSide ? whiteside : blackside;
|
||||
trgt.push_back(srcVertices[a]);
|
||||
|
||||
// if there's an intersection, put an end vertex there, switch to the other side's mesh,
|
||||
// and add a starting vertex there, too
|
||||
bool isPlaneHit = IntersectSegmentPlane(p, n, e0, e1, isCurrentlyOnWhiteSide, ei);
|
||||
if( isPlaneHit )
|
||||
{
|
||||
if( trgt.empty() || (trgt.back() - ei).SquareLength() > 1e-12 )
|
||||
trgt.push_back(ei);
|
||||
isCurrentlyOnWhiteSide = !isCurrentlyOnWhiteSide;
|
||||
std::vector<IfcVector3>& newtrgt = isCurrentlyOnWhiteSide ? whiteside : blackside;
|
||||
newtrgt.push_back(ei);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int newcount = 0;
|
||||
bool was_outside_boundary = !PointInPoly(proj * in[vidx], profile->verts);
|
||||
// the part on the white side can be written into the target mesh right away
|
||||
WritePolygon(whiteside, result);
|
||||
|
||||
// used any more?
|
||||
//size_t last_intersected_boundary_segment;
|
||||
IfcVector3 last_intersected_boundary_point;
|
||||
// The black part is the piece we need to get rid of, but only the part of it within the boundary polygon.
|
||||
// So we now need to construct all the polygons that result from BlackSidePoly minus BoundaryPoly.
|
||||
FilterPolygon(blackside);
|
||||
|
||||
bool extra_point_flag = false;
|
||||
IfcVector3 extra_point;
|
||||
// Complicated, II. We run along the polygon. a) When we're inside the boundary, we run on until we hit an
|
||||
// intersection, which means we're leaving it. We then start a new out poly there. b) When we're outside the
|
||||
// boundary, we start collecting vertices until we hit an intersection, then we run along the boundary until we hit
|
||||
// an intersection, then we switch back to the poly and run on on this one again, and so on until we got a closed
|
||||
// loop. Then we continue with the path we left to catch potential additional polys on the other side of the
|
||||
// boundary as described in a)
|
||||
if( !blackside.empty() )
|
||||
{
|
||||
// poly edge index, intersection point, edge index in boundary poly
|
||||
std::vector<boost::tuple<size_t, IfcVector3, size_t> > intersections;
|
||||
bool startedInside = PointInPoly(proj * blackside.front(), profile->verts);
|
||||
bool isCurrentlyInside = startedInside;
|
||||
|
||||
IfcVector3 enter_volume;
|
||||
bool entered_volume_flag = false;
|
||||
std::vector<std::pair<size_t, IfcVector3> > intersected_boundary;
|
||||
|
||||
for(unsigned int i = 0; i < *iit; ++i) {
|
||||
// current segment: [i,i+1 mod size] or [*extra_point,i] if extra_point_flag is set
|
||||
const IfcVector3& e0 = extra_point_flag ? extra_point : in[vidx+i];
|
||||
const IfcVector3& e1 = extra_point_flag ? in[vidx+i] : in[vidx+(i+1)%*iit];
|
||||
for( size_t a = 0; a < blackside.size(); ++a )
|
||||
{
|
||||
const IfcVector3 e0 = proj * blackside[a];
|
||||
const IfcVector3 e1 = proj * blackside[(a + 1) % blackside.size()];
|
||||
|
||||
// does the current segment intersect the polygonal boundary?
|
||||
const IfcVector3& e0_plane = proj * e0;
|
||||
const IfcVector3& e1_plane = proj * e1;
|
||||
|
||||
intersected_boundary_segments.clear();
|
||||
intersected_boundary_points.clear();
|
||||
|
||||
const bool is_outside_boundary = !PointInPoly(e1_plane, profile->verts);
|
||||
const bool is_boundary_intersection = is_outside_boundary != was_outside_boundary;
|
||||
|
||||
IntersectsBoundaryProfile(e0_plane, e1_plane, profile->verts,
|
||||
intersected_boundary_segments,
|
||||
intersected_boundary_points);
|
||||
|
||||
ai_assert(!is_boundary_intersection || !intersected_boundary_segments.empty());
|
||||
|
||||
// does the current segment intersect the plane?
|
||||
// (no extra check if this is an extra point)
|
||||
IfcVector3 isectpos;
|
||||
const Intersect isect = extra_point_flag ? Intersect_No : IntersectSegmentPlane(p,n,e0,e1,isectpos);
|
||||
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
if (isect == Intersect_Yes) {
|
||||
const IfcFloat f = std::fabs((isectpos - p)*n);
|
||||
ai_assert(f < 1e-5);
|
||||
}
|
||||
#endif
|
||||
|
||||
const bool is_white_side = (e0-p)*n >= -1e-6;
|
||||
|
||||
// e0 on good side of plane? (i.e. we should keep all geometry on this side)
|
||||
if (is_white_side) {
|
||||
// but is there an intersection in e0-e1 and is e1 in the clipping
|
||||
// boundary? In this case, generate a line that only goes to the
|
||||
// intersection point.
|
||||
if (isect == Intersect_Yes && !is_outside_boundary) {
|
||||
outvert.push_back(e0);
|
||||
++newcount;
|
||||
|
||||
outvert.push_back(isectpos);
|
||||
++newcount;
|
||||
|
||||
/*
|
||||
// this is, however, only a line that goes to the plane, but not
|
||||
// necessarily to the point where the bounding volume on the
|
||||
// black side of the plane is hit. So basically, we need another
|
||||
// check for [isectpos-e1], which should yield an intersection
|
||||
// point.
|
||||
extra_point_flag = true;
|
||||
extra_point = isectpos;
|
||||
|
||||
was_outside_boundary = true;
|
||||
continue; */
|
||||
|
||||
// [isectpos, enter_volume] potentially needs extra points.
|
||||
// For this, we determine the intersection point with the
|
||||
// bounding volume and project it onto the plane.
|
||||
/*
|
||||
const IfcVector3& enter_volume_proj = proj * enter_volume;
|
||||
const IfcVector3& enter_isectpos = proj * isectpos;
|
||||
|
||||
intersected_boundary_segments.clear();
|
||||
intersected_boundary_points.clear();
|
||||
|
||||
IntersectsBoundaryProfile(enter_volume_proj, enter_isectpos, profile->verts,
|
||||
intersected_boundary_segments,
|
||||
intersected_boundary_points);
|
||||
|
||||
if(!intersected_boundary_segments.empty()) {
|
||||
|
||||
vec = vec + ((p - vec) * n) * n;
|
||||
intersected_boundary.clear();
|
||||
IntersectsBoundaryProfile(e0, e1, profile->verts, isCurrentlyInside, intersected_boundary);
|
||||
// sort the hits by distance from e0 to get the correct in/out/in sequence. Manually :-( I miss you, C++11.
|
||||
if( intersected_boundary.size() > 1 )
|
||||
{
|
||||
bool keepSorting = true;
|
||||
while( keepSorting )
|
||||
{
|
||||
keepSorting = false;
|
||||
for( size_t b = 0; b < intersected_boundary.size() - 1; ++b )
|
||||
{
|
||||
if( (intersected_boundary[b + 1].second - e0).SquareLength() < (intersected_boundary[b].second - e0).SquareLength() )
|
||||
{
|
||||
keepSorting = true;
|
||||
std::swap(intersected_boundary[b + 1], intersected_boundary[b]);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//entered_volume_flag = true;
|
||||
}
|
||||
else {
|
||||
outvert.push_back(e0);
|
||||
++newcount;
|
||||
// now add them to the list of intersections
|
||||
for( size_t b = 0; b < intersected_boundary.size(); ++b )
|
||||
intersections.push_back(boost::make_tuple(a, proj_inv * intersected_boundary[b].second, intersected_boundary[b].first));
|
||||
|
||||
// and calculate our new inside/outside state
|
||||
if( intersected_boundary.size() & 1 )
|
||||
isCurrentlyInside = !isCurrentlyInside;
|
||||
}
|
||||
|
||||
// we got a list of in-out-combinations of intersections. That should be an even number of intersections, or
|
||||
// we're fucked.
|
||||
if( (intersections.size() & 1) != 0 )
|
||||
{
|
||||
IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if( intersections.size() > 1 )
|
||||
{
|
||||
// If we started outside, the first intersection is a out->in intersection. Cycle them so that it
|
||||
// starts with an intersection leaving the boundary
|
||||
if( !startedInside )
|
||||
for( size_t b = 0; b < intersections.size() - 1; ++b )
|
||||
std::swap(intersections[b], intersections[(b + intersections.size() - 1) % intersections.size()]);
|
||||
|
||||
// Filter pairs of out->in->out that lie too close to each other.
|
||||
for( size_t a = 0; intersections.size() > 0 && a < intersections.size() - 1; /**/ )
|
||||
{
|
||||
if( (intersections[a].get<1>() - intersections[(a + 1) % intersections.size()].get<1>()).SquareLength() < 1e-10 )
|
||||
intersections.erase(intersections.begin() + a, intersections.begin() + a + 2);
|
||||
else
|
||||
a++;
|
||||
}
|
||||
if( intersections.size() > 1 && (intersections.back().get<1>() - intersections.front().get<1>()).SquareLength() < 1e-10 )
|
||||
{
|
||||
intersections.pop_back(); intersections.erase(intersections.begin());
|
||||
}
|
||||
}
|
||||
// e0 on bad side of plane, e1 on good (i.e. we should remove geometry on this side,
|
||||
// but only if it is within the bounding volume).
|
||||
else if (isect == Intersect_Yes) {
|
||||
// is e0 within the clipping volume? Insert the intersection point
|
||||
// of [e0,e1] and the plane instead of e0.
|
||||
if(was_outside_boundary) {
|
||||
outvert.push_back(e0);
|
||||
}
|
||||
else {
|
||||
if(entered_volume_flag) {
|
||||
const IfcVector3& fix_point = enter_volume + ((p - enter_volume) * n) * n;
|
||||
outvert.push_back(fix_point);
|
||||
++newcount;
|
||||
}
|
||||
|
||||
outvert.push_back(isectpos);
|
||||
|
||||
// no intersections at all: either completely inside the boundary, so everything gets discarded, or completely outside.
|
||||
// in the latter case we're implementional lost. I'm simply going to ignore this, so a large poly will not get any
|
||||
// holes if the boundary is smaller and does not touch it anywhere.
|
||||
if( intersections.empty() )
|
||||
{
|
||||
// starting point was outside -> everything is outside the boundary -> nothing is clipped -> add black side
|
||||
// to result mesh unchanged
|
||||
if( !startedInside )
|
||||
{
|
||||
outvertcnt.push_back(blackside.size());
|
||||
outvert.insert(outvert.end(), blackside.begin(), blackside.end());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// starting point was inside the boundary -> everything is inside the boundary -> nothing is spared from the
|
||||
// clipping -> nothing left to add to the result mesh
|
||||
continue;
|
||||
}
|
||||
entered_volume_flag = false;
|
||||
++newcount;
|
||||
}
|
||||
else { // no intersection with plane or parallel; e0,e1 are on the bad side
|
||||
|
||||
// did we just pass the boundary line to the poly bounding?
|
||||
if (is_boundary_intersection) {
|
||||
// determine the direction in which we're marching along the boundary polygon. If the src poly is faced upwards
|
||||
// and the boundary is also winded this way, we need to march *backwards* on the boundary.
|
||||
const IfcVector3 polyNormal = IfcMatrix3(proj) * TempMesh::ComputePolygonNormal(blackside.data(), blackside.size());
|
||||
bool marchBackwardsOnBoundary = (profileNormal * polyNormal) >= 0.0;
|
||||
|
||||
// and are now outside the clipping boundary?
|
||||
if (is_outside_boundary) {
|
||||
// in this case, get the point where the clipping boundary
|
||||
// was entered first. Then, get the point where the clipping
|
||||
// boundary volume was left! These two points with the plane
|
||||
// normal form another plane that intersects the clipping
|
||||
// volume. There are two ways to get from the first to the
|
||||
// second point along the intersection curve, try to pick the
|
||||
// one that lies within the current polygon.
|
||||
// Build closed loops from these intersections. Starting from an intersection leaving the boundary we
|
||||
// walk along the polygon to the next intersection (which should be an IS entering the boundary poly).
|
||||
// From there we walk along the boundary until we hit another intersection leaving the boundary,
|
||||
// walk along the poly to the next IS and so on until we're back at the starting point.
|
||||
// We remove every intersection we "used up", so any remaining intersection is the start of a new loop.
|
||||
while( !intersections.empty() )
|
||||
{
|
||||
std::vector<IfcVector3> resultpoly;
|
||||
size_t currentIntersecIdx = 0;
|
||||
|
||||
// TODO this approach doesn't handle all cases
|
||||
while( true )
|
||||
{
|
||||
ai_assert(intersections.size() > currentIntersecIdx + 1);
|
||||
boost::tuple<size_t, IfcVector3, size_t> currintsec = intersections[currentIntersecIdx + 0];
|
||||
boost::tuple<size_t, IfcVector3, size_t> nextintsec = intersections[currentIntersecIdx + 1];
|
||||
intersections.erase(intersections.begin() + currentIntersecIdx, intersections.begin() + currentIntersecIdx + 2);
|
||||
|
||||
// ...
|
||||
// we start with an in->out intersection
|
||||
resultpoly.push_back(currintsec.get<1>());
|
||||
// climb along the polygon to the next intersection, which should be an out->in
|
||||
size_t numPolyPoints = (currintsec.get<0>() > nextintsec.get<0>() ? blackside.size() : 0)
|
||||
+ nextintsec.get<0>() - currintsec.get<0>();
|
||||
for( size_t a = 1; a <= numPolyPoints; ++a )
|
||||
resultpoly.push_back(blackside[(currintsec.get<0>() + a) % blackside.size()]);
|
||||
// put the out->in intersection
|
||||
resultpoly.push_back(nextintsec.get<1>());
|
||||
|
||||
IfcFloat d = 1e20;
|
||||
IfcVector3 vclosest;
|
||||
BOOST_FOREACH(const IfcVector3& v, intersected_boundary_points) {
|
||||
const IfcFloat dn = (v-e1_plane).SquareLength();
|
||||
if (dn < d) {
|
||||
d = dn;
|
||||
vclosest = v;
|
||||
// generate segments along the boundary polygon that lie in the poly's plane until we hit another intersection
|
||||
IfcVector3 startingPoint = proj * nextintsec.get<1>();
|
||||
size_t currentBoundaryEdgeIdx = (nextintsec.get<2>() + (marchBackwardsOnBoundary ? 1 : 0)) % profile->verts.size();
|
||||
size_t nextIntsecIdx = SIZE_MAX;
|
||||
while( nextIntsecIdx == SIZE_MAX )
|
||||
{
|
||||
IfcFloat t = 1e10;
|
||||
|
||||
size_t nextBoundaryEdgeIdx = marchBackwardsOnBoundary ? (currentBoundaryEdgeIdx + profile->verts.size() - 1) : currentBoundaryEdgeIdx + 1;
|
||||
nextBoundaryEdgeIdx %= profile->verts.size();
|
||||
// vertices of the current boundary segments
|
||||
IfcVector3 currBoundaryPoint = profile->verts[currentBoundaryEdgeIdx];
|
||||
IfcVector3 nextBoundaryPoint = profile->verts[nextBoundaryEdgeIdx];
|
||||
// project the two onto the polygon
|
||||
if( std::abs(polyNormal.z) > 1e-5 )
|
||||
{
|
||||
currBoundaryPoint.z = startingPoint.z + (currBoundaryPoint.x - startingPoint.x) * polyNormal.x/polyNormal.z + (currBoundaryPoint.y - startingPoint.y) * polyNormal.y/polyNormal.z;
|
||||
nextBoundaryPoint.z = startingPoint.z + (nextBoundaryPoint.x - startingPoint.x) * polyNormal.x/polyNormal.z + (nextBoundaryPoint.y - startingPoint.y) * polyNormal.y/polyNormal.z;
|
||||
}
|
||||
|
||||
// build a direction that goes along the boundary border but lies in the poly plane
|
||||
IfcVector3 boundaryPlaneNormal = ((nextBoundaryPoint - currBoundaryPoint) ^ profileNormal).Normalize();
|
||||
IfcVector3 dirAtPolyPlane = (boundaryPlaneNormal ^ polyNormal).Normalize() * (marchBackwardsOnBoundary ? -1.0 : 1.0);
|
||||
// if we can project the direction to the plane, we can calculate a maximum marching distance along that dir
|
||||
// until we finish that boundary segment and continue on the next
|
||||
if( std::abs(polyNormal.z) > 1e-5 )
|
||||
{
|
||||
t = std::min(t, (nextBoundaryPoint - startingPoint).Length());
|
||||
}
|
||||
|
||||
// check if the direction hits the loop start - if yes, we got a poly to output
|
||||
IfcVector3 dirToThatPoint = proj * resultpoly.front() - startingPoint;
|
||||
IfcFloat tpt = dirToThatPoint * dirAtPolyPlane;
|
||||
if( tpt > -1e-6 && tpt <= t && (dirToThatPoint - tpt * dirAtPolyPlane).SquareLength() < 1e-10 )
|
||||
{
|
||||
nextIntsecIdx = intersections.size(); // dirty hack to end marching along the boundary and signal the end of the loop
|
||||
t = tpt;
|
||||
}
|
||||
|
||||
// also check if the direction hits any in->out intersections earlier. If we hit one, we can switch back
|
||||
// to marching along the poly border from that intersection point
|
||||
for( size_t a = 0; a < intersections.size(); a += 2 )
|
||||
{
|
||||
dirToThatPoint = proj * intersections[a].get<1>() - startingPoint;
|
||||
tpt = dirToThatPoint * dirAtPolyPlane;
|
||||
if( tpt > -1e-6 && tpt <= t && (dirToThatPoint - tpt * dirAtPolyPlane).SquareLength() < 1e-10 )
|
||||
{
|
||||
nextIntsecIdx = a; // switch back to poly and march on from this in->out intersection
|
||||
t = tpt;
|
||||
}
|
||||
}
|
||||
|
||||
vclosest = proj_inv * vclosest;
|
||||
if(entered_volume_flag) {
|
||||
const IfcVector3& fix_point = vclosest + ((p - vclosest) * n) * n;
|
||||
outvert.push_back(fix_point);
|
||||
++newcount;
|
||||
|
||||
entered_volume_flag = false;
|
||||
// if we keep marching on the boundary, put the segment end point to the result poly and well... keep marching
|
||||
if( nextIntsecIdx == SIZE_MAX )
|
||||
{
|
||||
resultpoly.push_back(proj_inv * nextBoundaryPoint);
|
||||
currentBoundaryEdgeIdx = nextBoundaryEdgeIdx;
|
||||
startingPoint = nextBoundaryPoint;
|
||||
}
|
||||
|
||||
outvert.push_back(vclosest);
|
||||
++newcount;
|
||||
|
||||
//outvert.push_back(e1);
|
||||
//++newcount;
|
||||
}
|
||||
else {
|
||||
entered_volume_flag = true;
|
||||
|
||||
// we just entered the clipping boundary. Record the point
|
||||
// and the segment where we entered and also generate this point.
|
||||
//last_intersected_boundary_segment = intersected_boundary_segments.front();
|
||||
//last_intersected_boundary_point = intersected_boundary_points.front();
|
||||
|
||||
outvert.push_back(e0);
|
||||
++newcount;
|
||||
|
||||
IfcFloat d = 1e20;
|
||||
IfcVector3 vclosest;
|
||||
BOOST_FOREACH(const IfcVector3& v, intersected_boundary_points) {
|
||||
const IfcFloat dn = (v-e0_plane).SquareLength();
|
||||
if (dn < d) {
|
||||
d = dn;
|
||||
vclosest = v;
|
||||
}
|
||||
// quick endless loop check
|
||||
if( resultpoly.size() > blackside.size() + profile->verts.size() )
|
||||
{
|
||||
IFCImporter::LogError("Encountered endless loop while clipping polygon against poly-bounded half space.");
|
||||
break;
|
||||
}
|
||||
|
||||
enter_volume = proj_inv * vclosest;
|
||||
outvert.push_back(enter_volume);
|
||||
++newcount;
|
||||
}
|
||||
}
|
||||
// if not, we just keep the vertex
|
||||
else if (is_outside_boundary) {
|
||||
outvert.push_back(e0);
|
||||
++newcount;
|
||||
|
||||
entered_volume_flag = false;
|
||||
// we're back on the poly - if this is the intersection we started from, we got a closed loop.
|
||||
if( nextIntsecIdx >= intersections.size() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise it's another intersection. Continue marching from there.
|
||||
currentIntersecIdx = nextIntsecIdx;
|
||||
}
|
||||
|
||||
WritePolygon(resultpoly, result);
|
||||
}
|
||||
|
||||
was_outside_boundary = is_outside_boundary;
|
||||
extra_point_flag = false;
|
||||
}
|
||||
|
||||
if (!newcount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IfcVector3 vmin,vmax;
|
||||
ArrayBounds(&*(outvert.end()-newcount),newcount,vmin,vmax);
|
||||
|
||||
// filter our IfcFloat points - those may happen if a point lies
|
||||
// directly on the intersection line. However, due to IfcFloat
|
||||
// precision a bitwise comparison is not feasible to detect
|
||||
// this case.
|
||||
const IfcFloat epsilon = (vmax-vmin).SquareLength() / 1e6f;
|
||||
FuzzyVectorCompare fz(epsilon);
|
||||
|
||||
std::vector<IfcVector3>::iterator e = std::unique( outvert.end()-newcount, outvert.end(), fz );
|
||||
|
||||
if (e != outvert.end()) {
|
||||
newcount -= static_cast<unsigned int>(std::distance(e,outvert.end()));
|
||||
outvert.erase(e,outvert.end());
|
||||
}
|
||||
if (fz(*( outvert.end()-newcount),outvert.back())) {
|
||||
outvert.pop_back();
|
||||
--newcount;
|
||||
}
|
||||
if(newcount > 2) {
|
||||
result.vertcnt.push_back(newcount);
|
||||
}
|
||||
else while(newcount-->0) {
|
||||
result.verts.pop_back();
|
||||
}
|
||||
|
||||
}
|
||||
IFCImporter::LogDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)");
|
||||
}
|
||||
|
|
|
@ -579,6 +579,11 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
|||
IfcVector3 min = in[0];
|
||||
dir *= IfcMatrix3(trafo);
|
||||
|
||||
// reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction
|
||||
IfcVector3 profileNormal = TempMesh::ComputePolygonNormal( in.data(), in.size());
|
||||
if( profileNormal * dir < 0.0 )
|
||||
std::reverse( in.begin(), in.end());
|
||||
|
||||
std::vector<IfcVector3> nors;
|
||||
const bool openings = !!conv.apply_openings && conv.apply_openings->size();
|
||||
|
||||
|
@ -619,9 +624,9 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
|||
curmesh.vertcnt.push_back(4);
|
||||
|
||||
out.push_back(in[i]);
|
||||
out.push_back(in[i]+dir);
|
||||
out.push_back(in[next]+dir);
|
||||
out.push_back(in[next]);
|
||||
out.push_back(in[next]+dir);
|
||||
out.push_back(in[i]+dir);
|
||||
|
||||
if(openings) {
|
||||
if((in[i]-in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings,nors,temp,true, true, dir)) {
|
||||
|
@ -646,8 +651,12 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
|||
if(has_area) {
|
||||
|
||||
for(size_t n = 0; n < 2; ++n) {
|
||||
for(size_t i = size; i--; ) {
|
||||
out.push_back(in[i]+(n?dir:IfcVector3()));
|
||||
if( n > 0 ) {
|
||||
for(size_t i = 0; i < size; ++i )
|
||||
out.push_back(in[i]+dir);
|
||||
} else {
|
||||
for(size_t i = size; i--; )
|
||||
out.push_back(in[i]);
|
||||
}
|
||||
|
||||
curmesh.vertcnt.push_back(size);
|
||||
|
@ -699,10 +708,10 @@ void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool ProcessGeometricItem(const IfcRepresentationItem& geo, std::vector<unsigned int>& mesh_indices,
|
||||
bool ProcessGeometricItem(const IfcRepresentationItem& geo, unsigned int matid, std::vector<unsigned int>& mesh_indices,
|
||||
ConversionData& conv)
|
||||
{
|
||||
bool fix_orientation = true;
|
||||
bool fix_orientation = false;
|
||||
boost::shared_ptr< TempMesh > meshtmp = boost::make_shared<TempMesh>();
|
||||
if(const IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<IfcShellBasedSurfaceModel>()) {
|
||||
BOOST_FOREACH(boost::shared_ptr<const IfcShell> shell,shellmod->SbsmBoundary) {
|
||||
|
@ -716,24 +725,27 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, std::vector<unsigned
|
|||
IFCImporter::LogWarn("unexpected type error, IfcShell ought to inherit from IfcConnectedFaceSet");
|
||||
}
|
||||
}
|
||||
fix_orientation = true;
|
||||
}
|
||||
else if(const IfcConnectedFaceSet* fset = geo.ToPtr<IfcConnectedFaceSet>()) {
|
||||
ProcessConnectedFaceSet(*fset,*meshtmp.get(),conv);
|
||||
fix_orientation = true;
|
||||
}
|
||||
else if(const IfcSweptAreaSolid* swept = geo.ToPtr<IfcSweptAreaSolid>()) {
|
||||
ProcessSweptAreaSolid(*swept,*meshtmp.get(),conv);
|
||||
}
|
||||
else if(const IfcSweptDiskSolid* disk = geo.ToPtr<IfcSweptDiskSolid>()) {
|
||||
ProcessSweptDiskSolid(*disk,*meshtmp.get(),conv);
|
||||
fix_orientation = false;
|
||||
}
|
||||
else if(const IfcManifoldSolidBrep* brep = geo.ToPtr<IfcManifoldSolidBrep>()) {
|
||||
ProcessConnectedFaceSet(brep->Outer,*meshtmp.get(),conv);
|
||||
fix_orientation = true;
|
||||
}
|
||||
else if(const IfcFaceBasedSurfaceModel* surf = geo.ToPtr<IfcFaceBasedSurfaceModel>()) {
|
||||
BOOST_FOREACH(const IfcConnectedFaceSet& fc, surf->FbsmFaces) {
|
||||
ProcessConnectedFaceSet(fc,*meshtmp.get(),conv);
|
||||
}
|
||||
fix_orientation = true;
|
||||
}
|
||||
else if(const IfcBooleanResult* boolean = geo.ToPtr<IfcBooleanResult>()) {
|
||||
ProcessBoolean(*boolean,*meshtmp.get(),conv);
|
||||
|
@ -777,7 +789,7 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, std::vector<unsigned
|
|||
|
||||
aiMesh* const mesh = meshtmp->ToMesh();
|
||||
if(mesh) {
|
||||
mesh->mMaterialIndex = ProcessMaterials(geo,conv);
|
||||
mesh->mMaterialIndex = matid;
|
||||
mesh_indices.push_back(conv.meshes.size());
|
||||
conv.meshes.push_back(mesh);
|
||||
return true;
|
||||
|
@ -807,10 +819,11 @@ void AssignAddedMeshes(std::vector<unsigned int>& mesh_indices,aiNode* nd,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool TryQueryMeshCache(const IfcRepresentationItem& item,
|
||||
std::vector<unsigned int>& mesh_indices,
|
||||
std::vector<unsigned int>& mesh_indices, unsigned int mat_index,
|
||||
ConversionData& conv)
|
||||
{
|
||||
ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(&item);
|
||||
ConversionData::MeshCacheIndex idx(&item, mat_index);
|
||||
ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(idx);
|
||||
if (it != conv.cached_meshes.end()) {
|
||||
std::copy((*it).second.begin(),(*it).second.end(),std::back_inserter(mesh_indices));
|
||||
return true;
|
||||
|
@ -820,21 +833,25 @@ bool TryQueryMeshCache(const IfcRepresentationItem& item,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void PopulateMeshCache(const IfcRepresentationItem& item,
|
||||
const std::vector<unsigned int>& mesh_indices,
|
||||
const std::vector<unsigned int>& mesh_indices, unsigned int mat_index,
|
||||
ConversionData& conv)
|
||||
{
|
||||
conv.cached_meshes[&item] = mesh_indices;
|
||||
ConversionData::MeshCacheIndex idx(&item, mat_index);
|
||||
conv.cached_meshes[idx] = mesh_indices;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool ProcessRepresentationItem(const IfcRepresentationItem& item,
|
||||
bool ProcessRepresentationItem(const IfcRepresentationItem& item, unsigned int matid,
|
||||
std::vector<unsigned int>& mesh_indices,
|
||||
ConversionData& conv)
|
||||
{
|
||||
if (!TryQueryMeshCache(item,mesh_indices,conv)) {
|
||||
if(ProcessGeometricItem(item,mesh_indices,conv)) {
|
||||
// determine material
|
||||
unsigned int localmatid = ProcessMaterials(item.GetID(), matid, conv, true);
|
||||
|
||||
if (!TryQueryMeshCache(item,mesh_indices,localmatid,conv)) {
|
||||
if(ProcessGeometricItem(item,localmatid,mesh_indices,conv)) {
|
||||
if(mesh_indices.size()) {
|
||||
PopulateMeshCache(item,mesh_indices,conv);
|
||||
PopulateMeshCache(item,mesh_indices,localmatid,conv);
|
||||
}
|
||||
}
|
||||
else return false;
|
||||
|
|
|
@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
||||
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
|
||||
|
@ -428,7 +429,7 @@ void GetAbsTransform(aiMatrix4x4& out, const aiNode* nd, ConversionData& conv)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, ConversionData& conv)
|
||||
bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, unsigned int matid, ConversionData& conv)
|
||||
{
|
||||
// insert a custom node here, the cartesian transform operator is simply a conventional transformation matrix
|
||||
std::auto_ptr<aiNode> nd(new aiNode());
|
||||
|
@ -453,11 +454,12 @@ bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector<
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int localmatid = ProcessMaterials(mapped.GetID(),matid,conv,false);
|
||||
const IfcRepresentation& repr = mapped.MappingSource->MappedRepresentation;
|
||||
|
||||
bool got = false;
|
||||
BOOST_FOREACH(const IfcRepresentationItem& item, repr.Items) {
|
||||
if(!ProcessRepresentationItem(item,meshes,conv)) {
|
||||
if(!ProcessRepresentationItem(item,localmatid,meshes,conv)) {
|
||||
IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated");
|
||||
}
|
||||
else got = true;
|
||||
|
@ -557,7 +559,11 @@ void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector<
|
|||
if(!el.Representation) {
|
||||
return;
|
||||
}
|
||||
|
||||
// extract Color from metadata, if present
|
||||
unsigned int matid = ProcessMaterials( el.GetID(), std::numeric_limits<uint32_t>::max(), conv, false);
|
||||
std::vector<unsigned int> meshes;
|
||||
|
||||
// we want only one representation type, so bring them in a suitable order (i.e try those
|
||||
// that look as if we could read them quickly at first). This way of reading
|
||||
// representation is relatively generic and allows the concrete implementations
|
||||
|
@ -571,10 +577,10 @@ void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector<
|
|||
bool res = false;
|
||||
BOOST_FOREACH(const IfcRepresentationItem& item, repr->Items) {
|
||||
if(const IfcMappedItem* const geo = item.ToPtr<IfcMappedItem>()) {
|
||||
res = ProcessMappedItem(*geo,nd,subnodes,conv) || res;
|
||||
res = ProcessMappedItem(*geo,nd,subnodes,matid,conv) || res;
|
||||
}
|
||||
else {
|
||||
res = ProcessRepresentationItem(item,meshes,conv) || res;
|
||||
res = ProcessRepresentationItem(item,matid,meshes,conv) || res;
|
||||
}
|
||||
}
|
||||
// if we got something meaningful at this point, skip any further representations
|
||||
|
@ -671,10 +677,11 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
|
|||
const STEP::DB::RefMap& refs = conv.db.GetRefs();
|
||||
|
||||
// skip over space and annotation nodes - usually, these have no meaning in Assimp's context
|
||||
bool skipGeometry = false;
|
||||
if(conv.settings.skipSpaceRepresentations) {
|
||||
if(const IfcSpace* const space = el.ToPtr<IfcSpace>()) {
|
||||
IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
|
||||
return NULL;
|
||||
skipGeometry = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -844,8 +851,10 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
|
|||
conv.apply_openings = &openings;
|
||||
}
|
||||
|
||||
ProcessProductRepresentation(el,nd.get(),subnodes,conv);
|
||||
conv.apply_openings = conv.collect_openings = NULL;
|
||||
if (!skipGeometry) {
|
||||
ProcessProductRepresentation(el,nd.get(),subnodes,conv);
|
||||
conv.apply_openings = conv.collect_openings = NULL;
|
||||
}
|
||||
|
||||
if (subnodes.size()) {
|
||||
nd->mChildren = new aiNode*[subnodes.size()]();
|
||||
|
|
|
@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
||||
#include "IFCUtil.h"
|
||||
#include <limits>
|
||||
|
||||
namespace Assimp {
|
||||
namespace IFC {
|
||||
|
@ -132,45 +133,70 @@ void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionDat
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int ProcessMaterials(const IFC::IfcRepresentationItem& item, ConversionData& conv)
|
||||
unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat)
|
||||
{
|
||||
if (conv.materials.empty()) {
|
||||
aiString name;
|
||||
std::auto_ptr<aiMaterial> mat(new aiMaterial());
|
||||
|
||||
name.Set("<IFCDefault>");
|
||||
mat->AddProperty(&name,AI_MATKEY_NAME);
|
||||
|
||||
const aiColor4D col = aiColor4D(0.6f,0.6f,0.6f,1.0f);
|
||||
mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
|
||||
conv.materials.push_back(mat.release());
|
||||
}
|
||||
|
||||
STEP::DB::RefMapRange range = conv.db.GetRefs().equal_range(item.GetID());
|
||||
STEP::DB::RefMapRange range = conv.db.GetRefs().equal_range(id);
|
||||
for(;range.first != range.second; ++range.first) {
|
||||
if(const IFC::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::IfcStyledItem>()) {
|
||||
BOOST_FOREACH(const IFC::IfcPresentationStyleAssignment& as, styled->Styles) {
|
||||
BOOST_FOREACH(boost::shared_ptr<const IFC::IfcPresentationStyleSelect> sel, as.Styles) {
|
||||
|
||||
if (const IFC::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::IfcSurfaceStyle>(conv.db)) {
|
||||
if( const IFC::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::IfcSurfaceStyle>(conv.db) ) {
|
||||
// try to satisfy from cache
|
||||
ConversionData::MaterialCache::iterator mit = conv.cached_materials.find(surf);
|
||||
if( mit != conv.cached_materials.end() )
|
||||
return mit->second;
|
||||
|
||||
// not found, create new material
|
||||
const std::string side = static_cast<std::string>(surf->Side);
|
||||
if (side != "BOTH") {
|
||||
if( side != "BOTH" ) {
|
||||
IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: " + side);
|
||||
}
|
||||
|
||||
std::auto_ptr<aiMaterial> mat(new aiMaterial());
|
||||
|
||||
FillMaterial(mat.get(),surf,conv);
|
||||
FillMaterial(mat.get(), surf, conv);
|
||||
|
||||
conv.materials.push_back(mat.release());
|
||||
return conv.materials.size()-1;
|
||||
}
|
||||
}
|
||||
unsigned int matindex = conv.materials.size() - 1;
|
||||
conv.cached_materials[surf] = matindex;
|
||||
return matindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// no local material defined. If there's global one, use that instead
|
||||
if( prevMatId != std::numeric_limits<uint32_t>::max() )
|
||||
return prevMatId;
|
||||
|
||||
// we're still here - create an default material if required, or simply fail otherwise
|
||||
if( !forceDefaultMat )
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
|
||||
aiString name;
|
||||
name.Set("<IFCDefault>");
|
||||
// ConvertColorToString( color, name);
|
||||
|
||||
// look if there's already a default material with this base color
|
||||
for( size_t a = 0; a < conv.materials.size(); ++a )
|
||||
{
|
||||
aiString mname;
|
||||
conv.materials[a]->Get(AI_MATKEY_NAME, mname);
|
||||
if( name == mname )
|
||||
return (unsigned int)a;
|
||||
}
|
||||
|
||||
// we're here, yet - no default material with suitable color available. Generate one
|
||||
std::auto_ptr<aiMaterial> mat(new aiMaterial());
|
||||
mat->AddProperty(&name,AI_MATKEY_NAME);
|
||||
|
||||
const aiColor4D col = aiColor4D( 0.6f, 0.6f, 0.6f, 1.0f); // aiColor4D( color.r, color.g, color.b, 1.0f);
|
||||
mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
|
||||
conv.materials.push_back(mat.release());
|
||||
return (unsigned int) conv.materials.size() - 1;
|
||||
}
|
||||
|
||||
} // ! IFC
|
||||
|
|
|
@ -902,6 +902,14 @@ size_t CloseWindows(ContourVector& contours,
|
|||
curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4);
|
||||
curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size());
|
||||
|
||||
// compare base poly normal and contour normal to detect if we need to reverse the face winding
|
||||
IfcVector3 basePolyNormal = TempMesh::ComputePolygonNormal( curmesh.verts.data(), curmesh.vertcnt.front());
|
||||
std::vector<IfcVector3> worldSpaceContourVtx( it->contour.size());
|
||||
for( size_t a = 0; a < it->contour.size(); ++a )
|
||||
worldSpaceContourVtx[a] = minv * IfcVector3( it->contour[a].x, it->contour[a].y, 0.0);
|
||||
IfcVector3 contourNormal = TempMesh::ComputePolygonNormal( worldSpaceContourVtx.data(), worldSpaceContourVtx.size());
|
||||
bool reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0;
|
||||
|
||||
// XXX this algorithm is really a bit inefficient - both in terms
|
||||
// of constant factor and of asymptotic runtime.
|
||||
std::vector<bool>::const_iterator skipit = skipbegin;
|
||||
|
@ -909,9 +917,6 @@ size_t CloseWindows(ContourVector& contours,
|
|||
IfcVector3 start0;
|
||||
IfcVector3 start1;
|
||||
|
||||
IfcVector2 last_proj;
|
||||
//const IfcVector2& first_proj;
|
||||
|
||||
const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end();
|
||||
|
||||
bool drop_this_edge = false;
|
||||
|
@ -923,18 +928,8 @@ size_t CloseWindows(ContourVector& contours,
|
|||
IfcFloat best = static_cast<IfcFloat>(1e10);
|
||||
IfcVector3 bestv;
|
||||
|
||||
/* debug code to check for unwanted diagonal lines in window contours
|
||||
if (cit != cbegin) {
|
||||
const IfcVector2& vdelta = proj_point - last_proj;
|
||||
if (std::fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) {
|
||||
//continue;
|
||||
}
|
||||
} */
|
||||
|
||||
const IfcVector3& world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f);
|
||||
|
||||
last_proj = proj_point;
|
||||
|
||||
BOOST_FOREACH(const TempOpening* opening, refs) {
|
||||
BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) {
|
||||
const IfcFloat sqdist = (world_point - other).SquareLength();
|
||||
|
@ -956,8 +951,8 @@ size_t CloseWindows(ContourVector& contours,
|
|||
curmesh.verts.pop_back();
|
||||
}
|
||||
else {
|
||||
curmesh.verts.push_back(cit == cbegin ? world_point : bestv);
|
||||
curmesh.verts.push_back(cit == cbegin ? bestv : world_point);
|
||||
curmesh.verts.push_back(((cit == cbegin) != reverseCountourFaces) ? world_point : bestv);
|
||||
curmesh.verts.push_back(((cit == cbegin) != reverseCountourFaces) ? bestv : world_point);
|
||||
|
||||
curmesh.vertcnt.push_back(4);
|
||||
++closed;
|
||||
|
@ -969,8 +964,8 @@ size_t CloseWindows(ContourVector& contours,
|
|||
continue;
|
||||
}
|
||||
|
||||
curmesh.verts.push_back(world_point);
|
||||
curmesh.verts.push_back(bestv);
|
||||
curmesh.verts.push_back(reverseCountourFaces ? bestv : world_point);
|
||||
curmesh.verts.push_back(reverseCountourFaces ? world_point : bestv);
|
||||
|
||||
if (cit == cend - 1) {
|
||||
drop_this_edge = *skipit;
|
||||
|
@ -984,16 +979,11 @@ size_t CloseWindows(ContourVector& contours,
|
|||
curmesh.verts.pop_back();
|
||||
}
|
||||
else {
|
||||
curmesh.verts.push_back(start1);
|
||||
curmesh.verts.push_back(start0);
|
||||
curmesh.verts.push_back(reverseCountourFaces ? start0 : start1);
|
||||
curmesh.verts.push_back(reverseCountourFaces ? start1 : start0);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
BOOST_FOREACH(TempOpening* opening, refs) {
|
||||
//opening->wallPoints.clear();
|
||||
}*/
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -1194,16 +1184,13 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
|||
profile_data = opening.profileMesh2D.get();
|
||||
is_2d_source = true;
|
||||
}
|
||||
else {
|
||||
//continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// vertical extrusion
|
||||
if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
|
||||
continue;
|
||||
profile_data = opening.profileMesh2D.get();
|
||||
is_2d_source = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
std::vector<IfcVector3> profile_verts = profile_data->verts;
|
||||
|
|
172
code/IFCUtil.cpp
172
code/IFCUtil.cpp
|
@ -149,7 +149,7 @@ void TempMesh::RemoveDegenerates()
|
|||
for (std::vector<unsigned int>::iterator it = vertcnt.begin(); it != vertcnt.end(); ++inor) {
|
||||
const unsigned int pcount = *it;
|
||||
|
||||
if (normals[inor].SquareLength() < 1e-5f) {
|
||||
if (normals[inor].SquareLength() < 1e-10f) {
|
||||
it = vertcnt.erase(it);
|
||||
vit = verts.erase(vit, vit + pcount);
|
||||
|
||||
|
@ -166,6 +166,23 @@ void TempMesh::RemoveDegenerates()
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize)
|
||||
{
|
||||
std::vector<IfcFloat> temp((cnt+2)*3);
|
||||
for( size_t vofs = 0, i = 0; vofs < cnt; ++vofs )
|
||||
{
|
||||
const IfcVector3& v = vtcs[vofs];
|
||||
temp[i++] = v.x;
|
||||
temp[i++] = v.y;
|
||||
temp[i++] = v.z;
|
||||
}
|
||||
|
||||
IfcVector3 nor;
|
||||
NewellNormal<3, 3, 3>(nor, cnt, &temp[0], &temp[1], &temp[2]);
|
||||
return normalize ? nor.Normalize() : nor;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
||||
bool normalize,
|
||||
|
@ -214,37 +231,148 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
|||
// Compute the normal of the last polygon in the given mesh
|
||||
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const
|
||||
{
|
||||
size_t total = vertcnt.back(), vidx = verts.size() - total;
|
||||
std::vector<IfcFloat> temp((total+2)*3);
|
||||
for(size_t vofs = 0, cnt = 0; vofs < total; ++vofs) {
|
||||
const IfcVector3& v = verts[vidx+vofs];
|
||||
temp[cnt++] = v.x;
|
||||
temp[cnt++] = v.y;
|
||||
temp[cnt++] = v.z;
|
||||
}
|
||||
IfcVector3 nor;
|
||||
NewellNormal<3,3,3>(nor,total,&temp[0],&temp[1],&temp[2]);
|
||||
return normalize ? nor.Normalize() : nor;
|
||||
return ComputePolygonNormal(&verts[verts.size() - vertcnt.back()], vertcnt.back(), normalize);
|
||||
}
|
||||
|
||||
struct CompareVector
|
||||
{
|
||||
bool operator () (const IfcVector3& a, const IfcVector3& b) const
|
||||
{
|
||||
IfcVector3 d = a - b;
|
||||
IfcFloat eps = 1e-6;
|
||||
return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
|
||||
}
|
||||
};
|
||||
struct FindVector
|
||||
{
|
||||
IfcVector3 v;
|
||||
FindVector(const IfcVector3& p) : v(p) { }
|
||||
bool operator () (const IfcVector3& p) { return FuzzyVectorCompare(1e-6)(p, v); }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TempMesh::FixupFaceOrientation()
|
||||
{
|
||||
const IfcVector3 vavg = Center();
|
||||
|
||||
std::vector<IfcVector3> normals;
|
||||
ComputePolygonNormals(normals);
|
||||
// create a list of start indices for all faces to allow random access to faces
|
||||
std::vector<size_t> faceStartIndices(vertcnt.size());
|
||||
for( size_t i = 0, a = 0; a < vertcnt.size(); i += vertcnt[a], ++a )
|
||||
faceStartIndices[a] = i;
|
||||
|
||||
size_t c = 0, ofs = 0;
|
||||
BOOST_FOREACH(unsigned int cnt, vertcnt) {
|
||||
if (cnt>2){
|
||||
const IfcVector3& thisvert = verts[c];
|
||||
if (normals[ofs]*(thisvert-vavg) < 0) {
|
||||
std::reverse(verts.begin()+c,verts.begin()+cnt+c);
|
||||
// list all faces on a vertex
|
||||
std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex;
|
||||
for( size_t a = 0; a < vertcnt.size(); ++a )
|
||||
{
|
||||
for( size_t b = 0; b < vertcnt[a]; ++b )
|
||||
facesByVertex[verts[faceStartIndices[a] + b]].push_back(a);
|
||||
}
|
||||
// determine neighbourhood for all polys
|
||||
std::vector<size_t> neighbour(verts.size(), SIZE_MAX);
|
||||
std::vector<size_t> tempIntersect(10);
|
||||
for( size_t a = 0; a < vertcnt.size(); ++a )
|
||||
{
|
||||
for( size_t b = 0; b < vertcnt[a]; ++b )
|
||||
{
|
||||
size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % vertcnt[a];
|
||||
const std::vector<size_t>& facesOnB = facesByVertex[verts[ib]];
|
||||
const std::vector<size_t>& facesOnNB = facesByVertex[verts[nib]];
|
||||
// there should be exactly one or two faces which appear in both lists. Our face and the other side
|
||||
std::vector<size_t>::iterator sectstart = tempIntersect.begin();
|
||||
std::vector<size_t>::iterator sectend = std::set_intersection(
|
||||
facesOnB.begin(), facesOnB.end(), facesOnNB.begin(), facesOnNB.end(), sectstart);
|
||||
|
||||
if( std::distance(sectstart, sectend) != 2 )
|
||||
continue;
|
||||
if( *sectstart == a )
|
||||
++sectstart;
|
||||
neighbour[ib] = *sectstart;
|
||||
}
|
||||
}
|
||||
|
||||
// now we're getting started. We take the face which is the farthest away from the center. This face is most probably
|
||||
// facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring
|
||||
// faces to have the same winding until all faces have been tested.
|
||||
std::vector<bool> faceDone(vertcnt.size(), false);
|
||||
while( std::count(faceDone.begin(), faceDone.end(), false) != 0 )
|
||||
{
|
||||
// find the farthest of the remaining faces
|
||||
size_t farthestIndex = SIZE_MAX;
|
||||
IfcFloat farthestDistance = -1.0;
|
||||
for( size_t a = 0; a < vertcnt.size(); ++a )
|
||||
{
|
||||
if( faceDone[a] )
|
||||
continue;
|
||||
IfcVector3 faceCenter = std::accumulate(verts.begin() + faceStartIndices[a],
|
||||
verts.begin() + faceStartIndices[a] + vertcnt[a], IfcVector3(0.0)) / IfcFloat(vertcnt[a]);
|
||||
IfcFloat dst = (faceCenter - vavg).SquareLength();
|
||||
if( dst > farthestDistance ) { farthestDistance = dst; farthestIndex = a; }
|
||||
}
|
||||
|
||||
// calculate its normal and reverse the poly if its facing towards the mesh center
|
||||
IfcVector3 farthestNormal = ComputePolygonNormal(verts.data() + faceStartIndices[farthestIndex], vertcnt[farthestIndex]);
|
||||
IfcVector3 farthestCenter = std::accumulate(verts.begin() + faceStartIndices[farthestIndex],
|
||||
verts.begin() + faceStartIndices[farthestIndex] + vertcnt[farthestIndex], IfcVector3(0.0))
|
||||
/ IfcFloat(vertcnt[farthestIndex]);
|
||||
// We accapt a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
|
||||
// the file.
|
||||
if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 )
|
||||
{
|
||||
size_t fsi = faceStartIndices[farthestIndex], fvc = vertcnt[farthestIndex];
|
||||
std::reverse(verts.begin() + fsi, verts.begin() + fsi + fvc);
|
||||
std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc);
|
||||
// because of the neighbour index belonging to the edge starting with the point at the same index, we need to
|
||||
// cycle the neighbours through to match the edges again.
|
||||
// Before: points A - B - C - D with edge neighbour p - q - r - s
|
||||
// After: points D - C - B - A, reversed neighbours are s - r - q - p, but the should be
|
||||
// r q p s
|
||||
for( size_t a = 0; a < fvc - 1; ++a )
|
||||
std::swap(neighbour[fsi + a], neighbour[fsi + a + 1]);
|
||||
}
|
||||
faceDone[farthestIndex] = true;
|
||||
std::vector<size_t> todo;
|
||||
todo.push_back(farthestIndex);
|
||||
|
||||
// go over its neighbour faces recursively and adapt their winding order to match the farthest face
|
||||
while( !todo.empty() )
|
||||
{
|
||||
size_t tdf = todo.back();
|
||||
size_t vsi = faceStartIndices[tdf], vc = vertcnt[tdf];
|
||||
todo.pop_back();
|
||||
|
||||
// check its neighbours
|
||||
for( size_t a = 0; a < vc; ++a )
|
||||
{
|
||||
// ignore neighbours if we already checked them
|
||||
size_t nbi = neighbour[vsi + a];
|
||||
if( nbi == SIZE_MAX || faceDone[nbi] )
|
||||
continue;
|
||||
|
||||
const IfcVector3& vp = verts[vsi + a];
|
||||
size_t nbvsi = faceStartIndices[nbi], nbvc = vertcnt[nbi];
|
||||
std::vector<IfcVector3>::iterator it = std::find_if(verts.begin() + nbvsi, verts.begin() + nbvsi + nbvc, FindVector(vp));
|
||||
ai_assert(it != verts.begin() + nbvsi + nbvc);
|
||||
size_t nb_vidx = std::distance(verts.begin() + nbvsi, it);
|
||||
// two faces winded in the same direction should have a crossed edge, where one face has p0->p1 and the other
|
||||
// has p1'->p0'. If the next point on the neighbouring face is also the next on the current face, we need
|
||||
// to reverse the neighbour
|
||||
nb_vidx = (nb_vidx + 1) % nbvc;
|
||||
size_t oursideidx = (a + 1) % vc;
|
||||
if( FuzzyVectorCompare(1e-6)(verts[vsi + oursideidx], verts[nbvsi + nb_vidx]) )
|
||||
{
|
||||
std::reverse(verts.begin() + nbvsi, verts.begin() + nbvsi + nbvc);
|
||||
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
|
||||
for( size_t a = 0; a < nbvc - 1; ++a )
|
||||
std::swap(neighbour[nbvsi + a], neighbour[nbvsi + a + 1]);
|
||||
}
|
||||
|
||||
// either way we're done with the neighbour. Mark it as done and continue checking from there recursively
|
||||
faceDone[nbi] = true;
|
||||
todo.push_back(nbi);
|
||||
}
|
||||
}
|
||||
c += cnt;
|
||||
++ofs;
|
||||
|
||||
// no more faces reachable from this part of the surface, start over with a disjunct part and its farthest face
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,10 +97,10 @@ struct TempMesh
|
|||
void RemoveDegenerates();
|
||||
|
||||
void FixupFaceOrientation();
|
||||
|
||||
static IfcVector3 ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize = true);
|
||||
IfcVector3 ComputeLastPolygonNormal(bool normalize = true) const;
|
||||
void ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
||||
bool normalize = true,
|
||||
size_t ofs = 0) const;
|
||||
void ComputePolygonNormals(std::vector<IfcVector3>& normals, bool normalize = true, size_t ofs = 0) const;
|
||||
|
||||
void Swap(TempMesh& other);
|
||||
};
|
||||
|
@ -195,9 +195,19 @@ struct ConversionData
|
|||
std::vector<aiMesh*> meshes;
|
||||
std::vector<aiMaterial*> materials;
|
||||
|
||||
typedef std::map<const IFC::IfcRepresentationItem*, std::vector<unsigned int> > MeshCache;
|
||||
struct MeshCacheIndex {
|
||||
const IFC::IfcRepresentationItem* item; unsigned int matindex;
|
||||
MeshCacheIndex() : item(NULL), matindex(0) { }
|
||||
MeshCacheIndex(const IFC::IfcRepresentationItem* i, unsigned int mi) : item(i), matindex(mi) { }
|
||||
bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; }
|
||||
bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); }
|
||||
};
|
||||
typedef std::map<MeshCacheIndex, std::vector<unsigned int> > MeshCache;
|
||||
MeshCache cached_meshes;
|
||||
|
||||
typedef std::map<const IFC::IfcSurfaceStyle*, unsigned int> MaterialCache;
|
||||
MaterialCache cached_materials;
|
||||
|
||||
const IFCImporter::Settings& settings;
|
||||
|
||||
// Intermediate arrays used to resolve openings in walls: only one of them
|
||||
|
@ -220,7 +230,7 @@ struct FuzzyVectorCompare {
|
|||
|
||||
FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {}
|
||||
bool operator()(const IfcVector3& a, const IfcVector3& b) {
|
||||
return std::fabs((a-b).SquareLength()) < epsilon;
|
||||
return std::abs((a-b).SquareLength()) < epsilon;
|
||||
}
|
||||
|
||||
const IfcFloat epsilon;
|
||||
|
@ -263,11 +273,11 @@ IfcFloat ConvertSIPrefix(const std::string& prefix);
|
|||
bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv);
|
||||
|
||||
// IFCMaterial.cpp
|
||||
unsigned int ProcessMaterials(const IFC::IfcRepresentationItem& item, ConversionData& conv);
|
||||
unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat);
|
||||
|
||||
// IFCGeometry.cpp
|
||||
IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVector3& norOut);
|
||||
bool ProcessRepresentationItem(const IfcRepresentationItem& item, std::vector<unsigned int>& mesh_indices, ConversionData& conv);
|
||||
bool ProcessRepresentationItem(const IfcRepresentationItem& item, unsigned int matid, std::vector<unsigned int>& mesh_indices, ConversionData& conv);
|
||||
void AssignAddedMeshes(std::vector<unsigned int>& mesh_indices,aiNode* nd,ConversionData& /*conv*/);
|
||||
|
||||
void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
|
||||
|
|
|
@ -170,6 +170,10 @@ corresponding preprocessor flag to selectively disable formats.
|
|||
# include "AssbinLoader.h"
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
|
||||
# include "C4DImporter.h"
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -297,6 +301,10 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
|||
#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
|
||||
out.push_back( new AssbinImporter() );
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
|
||||
out.push_back( new C4DImporter() );
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
|
|||
ivdx = -1;
|
||||
int max_priority = -1;
|
||||
for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) {
|
||||
register const unsigned int dp = *piCur;
|
||||
const unsigned int dp = *piCur;
|
||||
|
||||
// must have live triangles
|
||||
if (piNumTriPtr[dp] > 0) {
|
||||
|
|
|
@ -346,7 +346,7 @@ struct VColorChannel : public VMapEntry
|
|||
if (!rawData.empty())
|
||||
return; // return if already allocated
|
||||
|
||||
register unsigned int m = num*dims;
|
||||
unsigned int m = num*dims;
|
||||
rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
|
||||
rawData.resize(m);
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
// copy all vertices
|
||||
for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) {
|
||||
register unsigned int idx = face.mIndices[q];
|
||||
unsigned int idx = face.mIndices[q];
|
||||
*pv++ = layer.mTempPoints[idx] /*- layer.mPivot*/;
|
||||
|
||||
// process UV coordinates
|
||||
|
@ -491,7 +491,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
|
|||
aiFace& face = *begin;
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
{
|
||||
register unsigned int tt = face.mIndices[i];
|
||||
unsigned int tt = face.mIndices[i];
|
||||
sSort.Add(mesh->mVertices[tt],tt,*it);
|
||||
}
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
|
|||
unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
|
||||
for (; beginIdx != endIdx; ++beginIdx)
|
||||
{
|
||||
register unsigned int idx = *beginIdx;
|
||||
unsigned int idx = *beginIdx;
|
||||
sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
|
||||
std::vector<unsigned int>::const_iterator a, end = poResult.end();
|
||||
|
||||
|
@ -533,7 +533,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
|
|||
unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
|
||||
for (; beginIdx != endIdx; ++beginIdx)
|
||||
{
|
||||
register unsigned int idx = *beginIdx;
|
||||
unsigned int idx = *beginIdx;
|
||||
if (vertexDone[idx])
|
||||
continue;
|
||||
sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
|
||||
|
@ -735,7 +735,7 @@ void LWOImporter::LoadLWOPoints(unsigned int length)
|
|||
{
|
||||
throw DeadlyImportError( "LWO2: Points chunk length is not multiple of vertexLen (12)");
|
||||
}
|
||||
register unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
|
||||
unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
|
||||
if (mIsLWO2)
|
||||
{
|
||||
mCurLayer->mTempPoints.reserve ( regularSize + (regularSize>>2u) );
|
||||
|
|
|
@ -377,7 +377,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
|
|||
for (unsigned int c = 0; c < 3;++c,++iCurrent) {
|
||||
|
||||
// validate vertex indices
|
||||
register unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
|
||||
unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
|
||||
if (iIndex >= m_pcHeader->numVertices) {
|
||||
DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range");
|
||||
iIndex = m_pcHeader->numVertices-1;
|
||||
|
|
|
@ -88,7 +88,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Report error to the log stream
|
||||
/*static*/ void MD5Parser::ReportError (const char* error, unsigned int line)
|
||||
/*static*/ AI_WONT_RETURN void MD5Parser::ReportError (const char* error, unsigned int line)
|
||||
{
|
||||
char szBuffer[1024];
|
||||
::sprintf(szBuffer,"[MD5] Line %i: %s",line,error);
|
||||
|
|
|
@ -367,7 +367,7 @@ public:
|
|||
* @param error Error message to be reported
|
||||
* @param line Index of the line where the error occured
|
||||
*/
|
||||
static void ReportError (const char* error, unsigned int line);
|
||||
AI_WONT_RETURN static void ReportError (const char* error, unsigned int line) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Report a specific warning
|
||||
|
|
|
@ -400,7 +400,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
if (TokenMatch(sz,"0x",2))
|
||||
{
|
||||
hasColor = true;
|
||||
register unsigned int numIdx = ::strtoul16(sz,&sz);
|
||||
unsigned int numIdx = ::strtoul16(sz,&sz);
|
||||
aiColor4D clr;
|
||||
clr.a = 1.f;
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@ namespace Assimp
|
|||
namespace Ogre
|
||||
{
|
||||
|
||||
void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "")
|
||||
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error)
|
||||
{
|
||||
if (!error.empty())
|
||||
{
|
||||
|
|
|
@ -170,7 +170,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
|
|||
|
||||
// Find meshes to merge with us
|
||||
for (unsigned int a = i+1; a < pNode->mNumMeshes;++a) {
|
||||
register unsigned int am = pNode->mMeshes[a];
|
||||
unsigned int am = pNode->mMeshes[a];
|
||||
if (meshes[am].instance_cnt == 1 && CanJoin(im,am,verts,faces)) {
|
||||
|
||||
merge_list.push_back(mScene->mMeshes[am]);
|
||||
|
|
|
@ -201,7 +201,12 @@ template <class char_t>
|
|||
AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
|
||||
{
|
||||
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
||||
in += len+1;
|
||||
if (in[len] != '\0') {
|
||||
in += len+1;
|
||||
} else {
|
||||
// If EOF after the token make sure we don't go past end of buffer
|
||||
in += len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,24 @@ static const aiImporterDesc desc = {
|
|||
"ply"
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Internal stuff
|
||||
namespace
|
||||
{
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Checks that property index is within range
|
||||
template <class T>
|
||||
const T &GetProperty(const std::vector<T> &props, int idx)
|
||||
{
|
||||
if (idx >= props.size())
|
||||
throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
|
||||
|
||||
return props[idx];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
PLYImporter::PLYImporter()
|
||||
|
@ -431,13 +449,13 @@ void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
|
|||
if (0xFFFFFFFF != aiPositions[0])
|
||||
{
|
||||
vOut.x = PLY::PropertyInstance::ConvertTo<float>(
|
||||
(*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
|
||||
GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF != aiPositions[1])
|
||||
{
|
||||
vOut.y = PLY::PropertyInstance::ConvertTo<float>(
|
||||
(*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
|
||||
GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
|
||||
}
|
||||
// and add them to our nice list
|
||||
pvOut->push_back(vOut);
|
||||
|
@ -541,19 +559,19 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
|
|||
if (0xFFFFFFFF != aiPositions[0])
|
||||
{
|
||||
vOut.x = PLY::PropertyInstance::ConvertTo<float>(
|
||||
(*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
|
||||
GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF != aiPositions[1])
|
||||
{
|
||||
vOut.y = PLY::PropertyInstance::ConvertTo<float>(
|
||||
(*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
|
||||
GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF != aiPositions[2])
|
||||
{
|
||||
vOut.z = PLY::PropertyInstance::ConvertTo<float>(
|
||||
(*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]);
|
||||
GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]);
|
||||
}
|
||||
|
||||
// and add them to our nice list
|
||||
|
@ -659,28 +677,28 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
|
|||
|
||||
if (0xFFFFFFFF != aiPositions[0])
|
||||
{
|
||||
vOut.r = NormalizeColorValue((*i).alProperties[
|
||||
aiPositions[0]].avList.front(),aiTypes[0]);
|
||||
vOut.r = NormalizeColorValue(GetProperty((*i).alProperties,
|
||||
aiPositions[0]).avList.front(),aiTypes[0]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF != aiPositions[1])
|
||||
{
|
||||
vOut.g = NormalizeColorValue((*i).alProperties[
|
||||
aiPositions[1]].avList.front(),aiTypes[1]);
|
||||
vOut.g = NormalizeColorValue(GetProperty((*i).alProperties,
|
||||
aiPositions[1]).avList.front(),aiTypes[1]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF != aiPositions[2])
|
||||
{
|
||||
vOut.b = NormalizeColorValue((*i).alProperties[
|
||||
aiPositions[2]].avList.front(),aiTypes[2]);
|
||||
vOut.b = NormalizeColorValue(GetProperty((*i).alProperties,
|
||||
aiPositions[2]).avList.front(),aiTypes[2]);
|
||||
}
|
||||
|
||||
// assume 1.0 for the alpha channel ifit is not set
|
||||
if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
|
||||
else
|
||||
{
|
||||
vOut.a = NormalizeColorValue((*i).alProperties[
|
||||
aiPositions[3]].avList.front(),aiTypes[3]);
|
||||
vOut.a = NormalizeColorValue(GetProperty((*i).alProperties,
|
||||
aiPositions[3]).avList.front(),aiTypes[3]);
|
||||
}
|
||||
|
||||
// and add them to our nice list
|
||||
|
@ -773,11 +791,11 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
|
|||
// parse the list of vertex indices
|
||||
if (0xFFFFFFFF != iProperty)
|
||||
{
|
||||
const unsigned int iNum = (unsigned int)(*i).alProperties[iProperty].avList.size();
|
||||
const unsigned int iNum = (unsigned int)GetProperty((*i).alProperties, iProperty).avList.size();
|
||||
sFace.mIndices.resize(iNum);
|
||||
|
||||
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
|
||||
(*i).alProperties[iProperty].avList.begin();
|
||||
GetProperty((*i).alProperties, iProperty).avList.begin();
|
||||
|
||||
for (unsigned int a = 0; a < iNum;++a,++p)
|
||||
{
|
||||
|
@ -789,7 +807,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
|
|||
if (0xFFFFFFFF != iMaterialIndex)
|
||||
{
|
||||
sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
|
||||
(*i).alProperties[iMaterialIndex].avList.front(),eType2);
|
||||
GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2);
|
||||
}
|
||||
pvOut->push_back(sFace);
|
||||
}
|
||||
|
@ -800,7 +818,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
|
|||
// a value of -1 indicates a restart of the strip
|
||||
bool flip = false;
|
||||
for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
|
||||
const std::vector<PLY::PropertyInstance::ValueUnion>& quak = (*i).alProperties[iProperty].avList;
|
||||
const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty((*i).alProperties, iProperty).avList;
|
||||
pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
|
||||
|
||||
int aiTable[2] = {-1,-1};
|
||||
|
@ -851,30 +869,30 @@ void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avL
|
|||
if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
|
||||
else
|
||||
{
|
||||
clrOut->r = NormalizeColorValue(avList[
|
||||
aiPositions[0]].avList.front(),aiTypes[0]);
|
||||
clrOut->r = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[0]).avList.front(),aiTypes[0]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
|
||||
else
|
||||
{
|
||||
clrOut->g = NormalizeColorValue(avList[
|
||||
aiPositions[1]].avList.front(),aiTypes[1]);
|
||||
clrOut->g = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[1]).avList.front(),aiTypes[1]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
|
||||
else
|
||||
{
|
||||
clrOut->b = NormalizeColorValue(avList[
|
||||
aiPositions[2]].avList.front(),aiTypes[2]);
|
||||
clrOut->b = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[2]).avList.front(),aiTypes[2]);
|
||||
}
|
||||
|
||||
// assume 1.0 for the alpha channel ifit is not set
|
||||
if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
|
||||
else
|
||||
{
|
||||
clrOut->a = NormalizeColorValue(avList[
|
||||
aiPositions[3]].avList.front(),aiTypes[3]);
|
||||
clrOut->a = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[3]).avList.front(),aiTypes[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1025,7 +1043,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
|
|||
// handle phong power and shading mode
|
||||
int iMode;
|
||||
if (0xFFFFFFFF != iPhong) {
|
||||
float fSpec = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),ePhong);
|
||||
float fSpec = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),ePhong);
|
||||
|
||||
// if shininess is 0 (and the pow() calculation would therefore always
|
||||
// become 1, not depending on the angle), use gouraud lighting
|
||||
|
@ -1043,7 +1061,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
|
|||
|
||||
// handle opacity
|
||||
if (0xFFFFFFFF != iOpacity) {
|
||||
float fOpacity = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),eOpacity);
|
||||
float fOpacity = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),eOpacity);
|
||||
pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
|
||||
}
|
||||
|
||||
|
|
|
@ -794,7 +794,7 @@ bool PLY::PropertyInstance::ParseValue(
|
|||
{
|
||||
ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
|
||||
|
||||
register bool ret = true;
|
||||
bool ret = true;
|
||||
*pCurOut = pCur;
|
||||
switch (eType)
|
||||
{
|
||||
|
@ -841,7 +841,7 @@ bool PLY::PropertyInstance::ParseValueBinary(
|
|||
{
|
||||
ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
|
||||
|
||||
register bool ret = true;
|
||||
bool ret = true;
|
||||
switch (eType)
|
||||
{
|
||||
case EDT_UInt:
|
||||
|
|
|
@ -314,7 +314,7 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
|
|||
if (!tex->mWidth || !tex->mHeight)
|
||||
throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero");
|
||||
|
||||
register unsigned int mul = tex->mWidth * tex->mHeight;
|
||||
unsigned int mul = tex->mWidth * tex->mHeight;
|
||||
aiTexel* begin = tex->pcData = new aiTexel[mul];
|
||||
aiTexel* const end = & begin [mul];
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ inline void ArrayDelete(T**& in, unsigned int& num)
|
|||
// "don't remove" flag not set. Nodes with meshes are never deleted.
|
||||
bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
|
||||
{
|
||||
register bool b = false;
|
||||
bool b = false;
|
||||
|
||||
std::list<aiNode*> mine;
|
||||
for (unsigned int i = 0; i < node->mNumChildren;++i)
|
||||
|
@ -271,7 +271,7 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
|
|||
}
|
||||
|
||||
// handle texture coordinates
|
||||
register bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
|
||||
bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
|
||||
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real)
|
||||
{
|
||||
if (!pMesh->mTextureCoords[i])break;
|
||||
|
|
|
@ -106,7 +106,7 @@ void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh)
|
|||
std::vector<unsigned int> poResult;
|
||||
for (unsigned int c = 0; c < 3;++c)
|
||||
{
|
||||
register unsigned int idx = (*i).mIndices[c];
|
||||
unsigned int idx = (*i).mIndices[c];
|
||||
if (vertexDone[idx])continue;
|
||||
|
||||
sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup,
|
||||
|
|
|
@ -289,7 +289,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
|
||||
for (unsigned int q = 0; q < in.mNumIndices; ++q)
|
||||
{
|
||||
register unsigned int idx = in.mIndices[q];
|
||||
unsigned int idx = in.mIndices[q];
|
||||
|
||||
// process all bones of this index
|
||||
if (avw)
|
||||
|
|
|
@ -137,7 +137,7 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
|||
return ::strcasecmp(s1,s2);
|
||||
#else
|
||||
|
||||
register char c1, c2;
|
||||
char c1, c2;
|
||||
do {
|
||||
c1 = tolower(*s1++);
|
||||
c2 = tolower(*s2++);
|
||||
|
@ -156,7 +156,7 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
|||
*/
|
||||
inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
|
||||
{
|
||||
register int i = (int)b.length()-(int)a.length();
|
||||
int i = (int)b.length()-(int)a.length();
|
||||
return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
|
|||
return ::strncasecmp(s1,s2, n);
|
||||
|
||||
#else
|
||||
register char c1, c2;
|
||||
char c1, c2;
|
||||
unsigned int p = 0;
|
||||
do
|
||||
{
|
||||
|
|
|
@ -290,6 +290,8 @@ void CatmullClarkSubdivider::InternSubdivide (
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
// we want edges to go away before the recursive calls so begin a new scope
|
||||
EdgeMap edges;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
@ -572,6 +574,7 @@ void CatmullClarkSubdivider::InternSubdivide (
|
|||
}
|
||||
}
|
||||
}
|
||||
} // end of scope for edges, freeing its memory
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 7. Apply the next subdivision step.
|
||||
|
|
|
@ -225,7 +225,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
// make verts
|
||||
const float fy = (float)yy, fx = (float)xx;
|
||||
register unsigned tmp,tmp2;
|
||||
unsigned tmp,tmp2;
|
||||
*pv++ = aiVector3D(fx,fy, (float)data[(tmp2=x*yy) + xx] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx,fy+1, (float)data[(tmp=x*(yy+1)) + xx] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx+1,fy+1,(float)data[tmp + xx+1] * hscale + bheight);
|
||||
|
|
|
@ -120,7 +120,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
|
|||
* offset 2 and 3)
|
||||
*/
|
||||
if ((rounded = (int)info.mTranslation.x)) {
|
||||
float out;
|
||||
float out = 0.0f;
|
||||
szTemp[0] = 0;
|
||||
if (aiTextureMapMode_Wrap == info.mapU) {
|
||||
// Wrap - simple take the fraction of the field
|
||||
|
@ -153,7 +153,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
|
|||
* offset 2 and 3)
|
||||
*/
|
||||
if ((rounded = (int)info.mTranslation.y)) {
|
||||
float out;
|
||||
float out = 0.0f;
|
||||
szTemp[0] = 0;
|
||||
if (aiTextureMapMode_Wrap == info.mapV) {
|
||||
// Wrap - simple take the fraction of the field
|
||||
|
|
|
@ -1432,7 +1432,7 @@ aiColor3D XFileParser::ReadRGB()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Throws an exception with a line number and the given text.
|
||||
void XFileParser::ThrowException( const std::string& pText)
|
||||
AI_WONT_RETURN void XFileParser::ThrowException( const std::string& pText)
|
||||
{
|
||||
if( mIsBinaryFormat)
|
||||
throw DeadlyImportError( pText);
|
||||
|
|
|
@ -134,7 +134,7 @@ protected:
|
|||
aiColor4D ReadRGBA();
|
||||
|
||||
/** Throws an exception with a line number and the given text. */
|
||||
void ThrowException( const std::string& pText);
|
||||
AI_WONT_RETURN void ThrowException( const std::string& pText) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
/** Filters the imported hierarchy for some degenerated cases that some exporters produce.
|
||||
* @param pData The sub-hierarchy to filter
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
//! Virtual destructor
|
||||
virtual ~CIrrXML_IOStreamReader() {};
|
||||
virtual ~CIrrXML_IOStreamReader() {}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
//! Reads an amount of bytes from the file.
|
||||
|
|
|
@ -37,7 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/** @file DefaultLogger.h
|
||||
/** @file DefaultLogger.hpp
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_AI_DEFAULTLOGGER
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file export.hpp
|
||||
/** @file Exporter.hpp
|
||||
* @brief Defines the CPP-API for the Assimp export interface
|
||||
*/
|
||||
#ifndef AI_EXPORT_HPP_INC
|
||||
|
@ -181,7 +181,7 @@ public:
|
|||
* about the output data flow of the export process.
|
||||
* @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be NULL.
|
||||
* @param pPath Full target file name. Target must be accessible.
|
||||
* @param pPreprocessing Accepts any choice of the #aiPostProcessing enumerated
|
||||
* @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
|
||||
* flags, but in reality only a subset of them makes sense here. Specifying
|
||||
* 'preprocessing' flags is useful if the input scene does not conform to
|
||||
* Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
|
||||
|
|
|
@ -38,7 +38,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
/** @file IOStream.h
|
||||
/** @file IOStream.hpp
|
||||
* @brief File I/O wrappers for C++.
|
||||
*/
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file IOSystem.h
|
||||
/** @file IOSystem.hpp
|
||||
* @brief File system wrapper for C++. Inherit this class to supply
|
||||
* custom file handling logic to the Import library.
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file assimp.hpp
|
||||
/** @file Importer.hpp
|
||||
* @brief Defines the C++-API to the Open Asset Import Library.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_ASSIMP_HPP
|
||||
|
@ -624,8 +624,8 @@ public:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
/** Private, do not use. */
|
||||
ImporterPimpl* Pimpl() { return pimpl; };
|
||||
const ImporterPimpl* Pimpl() const { return pimpl; };
|
||||
ImporterPimpl* Pimpl() { return pimpl; }
|
||||
const ImporterPimpl* Pimpl() const { return pimpl; }
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file LogStream.h
|
||||
/** @file LogStream.hpp
|
||||
* @brief Abstract base class 'LogStream', representing an output log stream.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_LOGSTREAM_H
|
||||
|
|
|
@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file NullLogger.h
|
||||
/** @file NullLogger.hpp
|
||||
* @brief Dummy logger
|
||||
*/
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file ProgressHandler.h
|
||||
/** @file ProgressHandler.hpp
|
||||
* @brief Abstract base class 'ProgressHandler'.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_PROGRESSHANDLER_H
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
virtual void UpdateFileRead(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
|
||||
float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
|
||||
Update( f * 0.5f );
|
||||
};
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Progress callback for post-processing steps
|
||||
|
@ -113,7 +113,7 @@ public:
|
|||
virtual void UpdatePostProcess(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
|
||||
float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
|
||||
Update( f * 0.5f + 0.5f );
|
||||
};
|
||||
}
|
||||
|
||||
}; // !class ProgressHandler
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/** @file assert.h
|
||||
/** @file ai_assert.h
|
||||
*/
|
||||
#ifndef AI_DEBUG_H_INC
|
||||
#define AI_DEBUG_H_INC
|
||||
|
|
|
@ -122,10 +122,7 @@ ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn);
|
|||
* @param pFormatId ID string to specify to which format you want to export to. Use
|
||||
* aiGetExportFormatCount() / aiGetExportFormatDescription() to learn which export formats are available.
|
||||
* @param pFileName Output file to write
|
||||
* @param pIO custom IO implementation to be used. Use this if you use your own storage methods.
|
||||
* If none is supplied, a default implementation using standard file IO is used. Note that
|
||||
* #aiExportSceneToBlob is provided as convenience function to export to memory buffers.
|
||||
* @param pPreprocessing Accepts any choice of the #aiPostProcessing enumerated
|
||||
* @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
|
||||
* flags, but in reality only a subset of them makes sense here. Specifying
|
||||
* 'preprocessing' flags is useful if the input scene does not conform to
|
||||
* Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
|
||||
|
@ -183,7 +180,7 @@ ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene,
|
|||
|
||||
// --------------------------------------------------------------------------------
|
||||
/** Describes a blob of exported scene data. Use #aiExportSceneToBlob() to create a blob containing an
|
||||
* exported scene. The memory referred by this structure is owned by Assimp. Use #aiReleaseExportedFile()
|
||||
* exported scene. The memory referred by this structure is owned by Assimp.
|
||||
* to free its resources. Don't try to free the memory on your side - it will crash for most build configurations
|
||||
* due to conflicting heaps.
|
||||
*
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiFileIO.h
|
||||
/** @file cfileio.h
|
||||
* @brief Defines generic C routines to access memory-mapped files
|
||||
*/
|
||||
#ifndef AI_FILEIO_H_INC
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file assimp.h
|
||||
/** @file cimport.h
|
||||
* @brief Defines the C-API to the Open Asset Import Library.
|
||||
*/
|
||||
#ifndef AI_ASSIMP_H_INC
|
||||
|
@ -139,7 +139,17 @@ ASSIMP_API const C_STRUCT aiScene* aiImportFileEx(
|
|||
// --------------------------------------------------------------------------------
|
||||
/** Same as #aiImportFileEx, but adds an extra parameter containing importer settings.
|
||||
*
|
||||
* @param pFile Path and filename of the file to be imported,
|
||||
* expected to be a null-terminated c-string. NULL is not a valid value.
|
||||
* @param pFlags Optional post processing steps to be executed after
|
||||
* a successful import. Provide a bitwise combination of the
|
||||
* #aiPostProcessSteps flags.
|
||||
* @param pFS aiFileIO structure. Will be used to open the model file itself
|
||||
* and any other files the loader needs to open. Pass NULL to use the default
|
||||
* implementation.
|
||||
* @param pProps #aiPropertyStore instance containing import settings.
|
||||
* @return Pointer to the imported data or NULL if the import failed.
|
||||
* @note Include <aiFileIO.h> for the definition of #aiFileIO.
|
||||
* @see aiImportFileEx
|
||||
*/
|
||||
ASSIMP_API const C_STRUCT aiScene* aiImportFileExWithProperties(
|
||||
|
@ -188,7 +198,29 @@ ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemory(
|
|||
// --------------------------------------------------------------------------------
|
||||
/** Same as #aiImportFileFromMemory, but adds an extra parameter containing importer settings.
|
||||
*
|
||||
* @param pBuffer Pointer to the file data
|
||||
* @param pLength Length of pBuffer, in bytes
|
||||
* @param pFlags Optional post processing steps to be executed after
|
||||
* a successful import. Provide a bitwise combination of the
|
||||
* #aiPostProcessSteps flags. If you wish to inspect the imported
|
||||
* scene first in order to fine-tune your post-processing setup,
|
||||
* consider to use #aiApplyPostProcessing().
|
||||
* @param pHint An additional hint to the library. If this is a non empty string,
|
||||
* the library looks for a loader to support the file extension specified by pHint
|
||||
* and passes the file to the first matching loader. If this loader is unable to
|
||||
* completely the request, the library continues and tries to determine the file
|
||||
* format on its own, a task that may or may not be successful.
|
||||
* Check the return value, and you'll know ...
|
||||
* @param pProps #aiPropertyStore instance containing import settings.
|
||||
* @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 doesn't handle model formats that spread their
|
||||
* data across multiple files or even directories. Examples include
|
||||
* OBJ or MD3, which outsource parts of their material info into
|
||||
* external scripts. If you need full functionality, provide
|
||||
* a custom IOSystem to make Assimp find these files and use
|
||||
* the regular aiImportFileEx()/aiImportFileExWithProperties() API.
|
||||
* @see aiImportFileFromMemory
|
||||
*/
|
||||
ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemoryWithProperties(
|
||||
|
@ -210,7 +242,7 @@ ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemoryWithProperties(
|
|||
* meaning this is still the same #aiScene which you passed for pScene. However,
|
||||
* _if_ post-processing failed, the scene could now be NULL. That's quite a rare
|
||||
* case, post processing steps are not really designed to 'fail'. To be exact,
|
||||
* the #aiProcess_ValidateDS flag is currently the only post processing step
|
||||
* the #aiProcess_ValidateDataStructure flag is currently the only post processing step
|
||||
* which can actually cause the scene to be reset to NULL.
|
||||
*/
|
||||
ASSIMP_API const C_STRUCT aiScene* aiApplyPostProcessing(
|
||||
|
@ -266,7 +298,7 @@ ASSIMP_API void aiEnableVerboseLogging(aiBool d);
|
|||
// --------------------------------------------------------------------------------
|
||||
/** Detach a custom log stream from the libraries' logging system.
|
||||
*
|
||||
* This is the counterpart of #aiAttachPredefinedLogStream. If you attached a stream,
|
||||
* This is the counterpart of #aiAttachLogStream. If you attached a stream,
|
||||
* don't forget to detach it again.
|
||||
* @param stream The log stream to be detached.
|
||||
* @return AI_SUCCESS if the log stream has been detached successfully.
|
||||
|
@ -356,8 +388,9 @@ ASSIMP_API void aiReleasePropertyStore(C_STRUCT aiPropertyStore* p);
|
|||
* interface, properties are always shared by all imports. It is not possible to
|
||||
* specify them per import.
|
||||
*
|
||||
* @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
|
||||
* @param szName Name of the configuration property to be set. All supported
|
||||
* public properties are defined in the config.h header file (#AI_CONFIG_XXX).
|
||||
* public properties are defined in the config.h header file (AI_CONFIG_XXX).
|
||||
* @param value New value for the property
|
||||
*/
|
||||
ASSIMP_API void aiSetImportPropertyInteger(
|
||||
|
@ -372,8 +405,9 @@ ASSIMP_API void aiSetImportPropertyInteger(
|
|||
* interface, properties are always shared by all imports. It is not possible to
|
||||
* specify them per import.
|
||||
*
|
||||
* @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
|
||||
* @param szName Name of the configuration property to be set. All supported
|
||||
* public properties are defined in the config.h header file (#AI_CONFIG_XXX).
|
||||
* public properties are defined in the config.h header file (AI_CONFIG_XXX).
|
||||
* @param value New value for the property
|
||||
*/
|
||||
ASSIMP_API void aiSetImportPropertyFloat(
|
||||
|
@ -388,10 +422,10 @@ ASSIMP_API void aiSetImportPropertyFloat(
|
|||
* interface, properties are always shared by all imports. It is not possible to
|
||||
* specify them per import.
|
||||
*
|
||||
* @param property store to modify. Use #aiCreatePropertyStore to obtain a store.
|
||||
* @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
|
||||
* @param szName Name of the configuration property to be set. All supported
|
||||
* public properties are defined in the config.h header file (#AI_CONFIG_XXX).
|
||||
* @param value New value for the property
|
||||
* public properties are defined in the config.h header file (AI_CONFIG_XXX).
|
||||
* @param st New value for the property
|
||||
*/
|
||||
ASSIMP_API void aiSetImportPropertyString(
|
||||
C_STRUCT aiPropertyStore* store,
|
||||
|
@ -405,10 +439,10 @@ ASSIMP_API void aiSetImportPropertyString(
|
|||
* interface, properties are always shared by all imports. It is not possible to
|
||||
* specify them per import.
|
||||
*
|
||||
* @param property store to modify. Use #aiCreatePropertyStore to obtain a store.
|
||||
* @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
|
||||
* @param szName Name of the configuration property to be set. All supported
|
||||
* public properties are defined in the config.h header file (#AI_CONFIG_XXX).
|
||||
* @param value New value for the property
|
||||
* public properties are defined in the config.h header file (AI_CONFIG_XXX).
|
||||
* @param mat New value for the property
|
||||
*/
|
||||
ASSIMP_API void aiSetImportPropertyMatrix(
|
||||
C_STRUCT aiPropertyStore* store,
|
||||
|
|
|
@ -38,7 +38,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
/** @file aiColor4D.h
|
||||
/** @file color4.h
|
||||
* @brief RGBA color structure, including operators when compiling in C++
|
||||
*/
|
||||
#ifndef AI_COLOR4D_H_INC
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiColor4D.inl
|
||||
/** @file color4.inl
|
||||
* @brief Inline implementation of aiColor4t<TReal> operators
|
||||
*/
|
||||
#ifndef AI_COLOR4D_INL_INC
|
||||
|
|
|
@ -209,7 +209,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
"PP_RRM_EXCLUDE_LIST"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Configures the #aiProcess_PretransformVertices step to
|
||||
/** @brief Configures the #aiProcess_PreTransformVertices step to
|
||||
* keep the scene hierarchy. Meshes are moved to worldspace, but
|
||||
* no optimization is performed (read: meshes with equal materials are not
|
||||
* joined. The total number of meshes won't change).
|
||||
|
@ -224,7 +224,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
"PP_PTV_KEEP_HIERARCHY"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Configures the #aiProcess_PretransformVertices step to normalize
|
||||
/** @brief Configures the #aiProcess_PreTransformVertices step to normalize
|
||||
* all vertex components into the [-1,1] range. That is, a bounding box
|
||||
* for the whole scene is computed, the maximum component is taken and all
|
||||
* meshes are scaled appropriately (uniformly of course!).
|
||||
|
@ -234,7 +234,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
"PP_PTV_NORMALIZE"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Configures the #aiProcess_PretransformVertices step to use
|
||||
/** @brief Configures the #aiProcess_PreTransformVertices step to use
|
||||
* a users defined matrix as the scene root node transformation before
|
||||
* transforming vertices.
|
||||
* Property type: bool. Default value: false.
|
||||
|
@ -243,7 +243,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
"PP_PTV_ADD_ROOT_TRANSFORMATION"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Configures the #aiProcess_PretransformVertices step to use
|
||||
/** @brief Configures the #aiProcess_PreTransformVertices step to use
|
||||
* a users defined matrix as the scene root node transformation before
|
||||
* transforming vertices. This property correspond to the 'a1' component
|
||||
* of the transformation matrix.
|
||||
|
@ -376,7 +376,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Enumerates components of the aiScene and aiMesh data structures
|
||||
* that can be excluded from the import using the #aiPrpcess_RemoveComponent step.
|
||||
* that can be excluded from the import using the #aiProcess_RemoveComponent step.
|
||||
*
|
||||
* See the documentation to #aiProcess_RemoveComponent for more details.
|
||||
*/
|
||||
|
@ -715,7 +715,7 @@ enum aiComponent
|
|||
/** @brief Tells the MD3 loader which skin files to load.
|
||||
*
|
||||
* When loading MD3 files, Assimp checks whether a file
|
||||
* <md3_file_name>_<skin_name>.skin is existing. These files are used by
|
||||
* [md3_file_name]_[skin_name].skin is existing. These files are used by
|
||||
* Quake III to be able to assign different skins (e.g. red and blue team)
|
||||
* to models. 'default', 'red', 'blue' are typical skin names.
|
||||
* Property type: String. Default value: "default".
|
||||
|
@ -728,14 +728,14 @@ enum aiComponent
|
|||
* MD3 file. This can also be a search path.
|
||||
*
|
||||
* By default Assimp's behaviour is as follows: If a MD3 file
|
||||
* <tt><any_path>/models/<any_q3_subdir>/<model_name>/<file_name>.md3</tt> is
|
||||
* <tt>any_path/models/any_q3_subdir/model_name/file_name.md3</tt> is
|
||||
* loaded, the library tries to locate the corresponding shader file in
|
||||
* <tt><any_path>/scripts/<model_name>.shader</tt>. This property overrides this
|
||||
* <tt>any_path/scripts/model_name.shader</tt>. This property overrides this
|
||||
* behaviour. It can either specify a full path to the shader to be loaded
|
||||
* or alternatively the path (relative or absolute) to the directory where
|
||||
* the shaders for all MD3s to be loaded reside. Assimp attempts to open
|
||||
* <tt><dir>/<model_name>.shader</tt> first, <tt><dir>/<file_name>.shader</tt>
|
||||
* is the fallback file. Note that <dir> should have a terminal (back)slash.
|
||||
* <tt>IMPORT_MD3_SHADER_SRC/model_name.shader</tt> first, <tt>IMPORT_MD3_SHADER_SRC/file_name.shader</tt>
|
||||
* is the fallback file. Note that IMPORT_MD3_SHADER_SRC should have a terminal (back)slash.
|
||||
* Property type: String. Default value: n/a.
|
||||
*/
|
||||
#define AI_CONFIG_IMPORT_MD3_SHADER_SRC \
|
||||
|
@ -818,12 +818,13 @@ enum aiComponent
|
|||
/** @brief Ogre Importer detect the texture usage from its filename.
|
||||
*
|
||||
* Ogre material texture units do not define texture type, the textures usage
|
||||
* depends on the used shader or Ogres fixed pipeline. If this config property
|
||||
* depends on the used shader or Ogre's fixed pipeline. If this config property
|
||||
* is true Assimp will try to detect the type from the textures filename postfix:
|
||||
* _n, _nrm, _nrml, _normal, _normals and _normalmap for normal map, _s, _spec,
|
||||
* _specular and _specularmap for specular map, _l, _light, _lightmap, _occ
|
||||
* and _occlusion for light map, _disp and _displacement for displacement map.
|
||||
* The matching is case insensitive. Post fix is taken between last "_" and last ".".
|
||||
* The matching is case insensitive. Post fix is taken between the last
|
||||
* underscore and the last period.
|
||||
* Default behavior is to detect type from lower cased texture unit name by
|
||||
* matching against: normalmap, specularmap, lightmap and displacementmap.
|
||||
* For both cases if no match is found aiTextureType_DIFFUSE is used.
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiDefines.h
|
||||
/** @file defs.h
|
||||
* @brief Assimp build configuration setup. See the notes in the comment
|
||||
* blocks to find out how to customize _your_ Assimp build.
|
||||
*/
|
||||
|
@ -162,8 +162,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
# define AI_FORCE_INLINE inline
|
||||
#endif // (defined _MSC_VER)
|
||||
|
||||
#ifdef __clang__
|
||||
# define AI_WONT_RETURN_SUFFIX __attribute__((analyzer_noreturn))
|
||||
#ifdef __GNUC__
|
||||
# define AI_WONT_RETURN_SUFFIX __attribute__((noreturn))
|
||||
#else
|
||||
# define AI_WONT_RETURN_SUFFIX
|
||||
#endif // (defined __clang__)
|
||||
|
|
|
@ -98,8 +98,7 @@ struct aiImporterDesc
|
|||
/** Implementation comments, i.e. unimplemented features*/
|
||||
const char* mComments;
|
||||
|
||||
/** Any combination of the #aiLoaderFlags enumerated values.
|
||||
These flags indicate some characteristics common to many
|
||||
/** These flags indicate some characteristics common to many
|
||||
importers. */
|
||||
unsigned int mFlags;
|
||||
|
||||
|
|
|
@ -95,14 +95,9 @@ enum aiTextureOp
|
|||
aiTextureOp_SignedAdd = 0x5,
|
||||
|
||||
|
||||
/** @cond never
|
||||
* This value is not used. It forces the compiler to use at least
|
||||
* 32 Bit integers to represent this enum.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
_aiTextureOp_Force32Bit = INT_MAX
|
||||
#endif
|
||||
//! @endcond
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -131,14 +126,9 @@ enum aiTextureMapMode
|
|||
*/
|
||||
aiTextureMapMode_Mirror = 0x2,
|
||||
|
||||
/** @cond never
|
||||
* This value is not used. It forces the compiler to use at least
|
||||
* 32 Bit integers to represent this enum.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
_aiTextureMapMode_Force32Bit = INT_MAX
|
||||
#endif
|
||||
//! @endcond
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -176,14 +166,9 @@ enum aiTextureMapping
|
|||
aiTextureMapping_OTHER = 0x5,
|
||||
|
||||
|
||||
/** @cond never
|
||||
* This value is not used. It forces the compiler to use at least
|
||||
* 32 Bit integers to represent this enum.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
_aiTextureMapping_Force32Bit = INT_MAX
|
||||
#endif
|
||||
//! @endcond
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -296,14 +281,9 @@ enum aiTextureType
|
|||
aiTextureType_UNKNOWN = 0xC,
|
||||
|
||||
|
||||
/** @cond never
|
||||
* This value is not used. It forces the compiler to use at least
|
||||
* 32 Bit integers to represent this enum.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
_aiTextureType_Force32Bit = INT_MAX
|
||||
#endif
|
||||
//! @endcond
|
||||
};
|
||||
|
||||
#define AI_TEXTURE_TYPE_MAX aiTextureType_UNKNOWN
|
||||
|
@ -374,14 +354,9 @@ enum aiShadingMode
|
|||
aiShadingMode_Fresnel = 0xa,
|
||||
|
||||
|
||||
/** @cond never
|
||||
* This value is not used. It forces the compiler to use at least
|
||||
* 32 Bit integers to represent this enum.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
_aiShadingMode_Force32Bit = INT_MAX
|
||||
#endif
|
||||
//! @endcond
|
||||
};
|
||||
|
||||
|
||||
|
@ -420,14 +395,9 @@ enum aiTextureFlags
|
|||
*/
|
||||
aiTextureFlags_IgnoreAlpha = 0x4,
|
||||
|
||||
/** @cond never
|
||||
* This value is not used. It forces the compiler to use at least
|
||||
* 32 Bit integers to represent this enum.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
_aiTextureFlags_Force32Bit = INT_MAX
|
||||
#endif
|
||||
//! @endcond
|
||||
};
|
||||
|
||||
|
||||
|
@ -442,8 +412,8 @@ enum aiTextureFlags
|
|||
* @code
|
||||
* SourceColor * SourceBlend + DestColor * DestBlend
|
||||
* @endcode
|
||||
* where <DestColor> is the previous color in the framebuffer at this
|
||||
* position and <SourceColor> is the material colro before the transparency
|
||||
* where DestColor is the previous color in the framebuffer at this
|
||||
* position and SourceColor is the material colro before the transparency
|
||||
* calculation.<br>
|
||||
* This corresponds to the #AI_MATKEY_BLEND_FUNC property.
|
||||
*/
|
||||
|
@ -469,14 +439,9 @@ enum aiBlendMode
|
|||
// we don't need more for the moment, but we might need them
|
||||
// in future versions ...
|
||||
|
||||
/** @cond never
|
||||
* This value is not used. It forces the compiler to use at least
|
||||
* 32 Bit integers to represent this enum.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
_aiBlendMode_Force32Bit = INT_MAX
|
||||
#endif
|
||||
//! @endcond
|
||||
};
|
||||
|
||||
|
||||
|
@ -862,7 +827,9 @@ public:
|
|||
/** @brief Remove a given key from the list.
|
||||
*
|
||||
* The function fails if the key isn't found
|
||||
* @param pKey Key to be deleted */
|
||||
* @param pKey Key to be deleted
|
||||
* @param type Set by the AI_MATKEY_XXX macro
|
||||
* @param index Set by the AI_MATKEY_XXX macro */
|
||||
aiReturn RemoveProperty (const char* pKey,
|
||||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
@ -1330,6 +1297,8 @@ extern "C" {
|
|||
#define AI_MATKEY_TEXFLAGS_UNKNOWN(N) \
|
||||
AI_MATKEY_TEXFLAGS(aiTextureType_UNKNOWN,N)
|
||||
|
||||
//! @endcond
|
||||
//!
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Retrieve a material property with a specific key from the material
|
||||
*
|
||||
|
@ -1537,6 +1506,7 @@ ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMa
|
|||
* Pass NULL if you're not interested in this information. Otherwise,
|
||||
* pass a pointer to an array of two aiTextureMapMode's (one for each
|
||||
* axis, UV order).
|
||||
* @param[out] flags Receives the the texture flags.
|
||||
* @return AI_SUCCESS on success, otherwise something else. Have fun.*/
|
||||
// ---------------------------------------------------------------------------
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiMaterial.inl
|
||||
/** @file material.inl
|
||||
* @brief Defines the C++ getters for the material system
|
||||
*/
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiMatrix3x3.inl
|
||||
/** @file matrix3x3.inl
|
||||
* @brief Inline implementation of the 3x3 matrix operators
|
||||
*/
|
||||
#ifndef AI_MATRIX3x3_INL_INC
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiMatrix4x4t<TReal>.inl
|
||||
/** @file matrix4x4.inl
|
||||
* @brief Inline implementation of the 4x4 matrix operators
|
||||
*/
|
||||
#ifndef AI_MATRIX4x4_INL_INC
|
||||
|
|
|
@ -668,8 +668,7 @@ struct aiMesh
|
|||
}
|
||||
|
||||
//! Check whether the mesh contains positions. Provided no special
|
||||
//! scene flags are set (such as #AI_SCENE_FLAGS_ANIM_SKELETON_ONLY),
|
||||
//! this will always be true
|
||||
//! scene flags are set, this will always be true
|
||||
bool HasPositions() const
|
||||
{ return mVertices != NULL && mNumVertices > 0; }
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ enum aiPostProcessSteps
|
|||
/** <hr>Searches for redundant/unreferenced materials and removes them.
|
||||
*
|
||||
* This is especially useful in combination with the
|
||||
* #aiProcess_PretransformVertices and #aiProcess_OptimizeMeshes flags.
|
||||
* #aiProcess_PreTransformVertices and #aiProcess_OptimizeMeshes flags.
|
||||
* Both join small meshes with equal characteristics, but they can't do
|
||||
* their work if two meshes have different materials. Because several
|
||||
* material settings are lost during Assimp's import filters,
|
||||
|
@ -335,7 +335,7 @@ enum aiPostProcessSteps
|
|||
* To have the degenerate stuff not only detected and collapsed but
|
||||
* removed, try one of the following procedures:
|
||||
* <br><b>1.</b> (if you support lines and points for rendering but don't
|
||||
* want the degenerates)</br>
|
||||
* want the degenerates)<br>
|
||||
* <ul>
|
||||
* <li>Specify the #aiProcess_FindDegenerates flag.
|
||||
* </li>
|
||||
|
@ -345,7 +345,7 @@ enum aiPostProcessSteps
|
|||
* pipeline steps.
|
||||
* </li>
|
||||
* </ul>
|
||||
* <br><b>2.</b>(if you don't support lines and points at all)</br>
|
||||
* <br><b>2.</b>(if you don't support lines and points at all)<br>
|
||||
* <ul>
|
||||
* <li>Specify the #aiProcess_FindDegenerates flag.
|
||||
* </li>
|
||||
|
@ -550,7 +550,7 @@ enum aiPostProcessSteps
|
|||
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
/** @def aiProcessPreset_TargetRealtimeUse_Fast
|
||||
/** @def aiProcessPreset_TargetRealtime_Fast
|
||||
* @brief Default postprocess configuration optimizing the data for real-time rendering.
|
||||
*
|
||||
* Applications would want to use this preset to load models on end-user PCs,
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiQuaterniont.inl
|
||||
/** @file quaternion.inl
|
||||
* @brief Inline implementation of aiQuaterniont<TReal> operators
|
||||
*/
|
||||
#ifndef AI_QUATERNION_INL_INC
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiScene.h
|
||||
/** @file scene.h
|
||||
* @brief Defines the data structures in which the imported scene is returned.
|
||||
*/
|
||||
#ifndef __AI_SCENE_H_INC__
|
||||
|
@ -182,8 +182,6 @@ struct aiNode
|
|||
}
|
||||
|
||||
|
||||
/** @override
|
||||
*/
|
||||
inline const aiNode* FindNode(const char* name) const
|
||||
{
|
||||
if (!::strcmp( mName.data,name))return this;
|
||||
|
@ -217,7 +215,7 @@ struct aiNode
|
|||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @def AI_SCENE_FLAGS_INCOMPLETE
|
||||
/**
|
||||
* Specifies that the scene data structure that was imported is not complete.
|
||||
* This flag bypasses some internal validations and allows the import
|
||||
* of animation skeletons, material libraries or camera animation paths
|
||||
|
@ -225,14 +223,14 @@ struct aiNode
|
|||
*/
|
||||
#define AI_SCENE_FLAGS_INCOMPLETE 0x1
|
||||
|
||||
/** @def AI_SCENE_FLAGS_VALIDATED
|
||||
/**
|
||||
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
|
||||
* if the validation is successful. In a validated scene you can be sure that
|
||||
* any cross references in the data structure (e.g. vertex indices) are valid.
|
||||
*/
|
||||
#define AI_SCENE_FLAGS_VALIDATED 0x2
|
||||
|
||||
/** @def AI_SCENE_FLAGS_VALIDATION_WARNING
|
||||
/**
|
||||
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
|
||||
* if the validation is successful but some issues have been found.
|
||||
* This can for example mean that a texture that does not exist is referenced
|
||||
|
@ -242,7 +240,7 @@ struct aiNode
|
|||
*/
|
||||
#define AI_SCENE_FLAGS_VALIDATION_WARNING 0x4
|
||||
|
||||
/** @def AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
|
||||
/**
|
||||
* This flag is currently only set by the aiProcess_JoinIdenticalVertices step.
|
||||
* It indicates that the vertices of the output meshes aren't in the internal
|
||||
* verbose format anymore. In the verbose format all vertices are unique,
|
||||
|
@ -250,7 +248,7 @@ struct aiNode
|
|||
*/
|
||||
#define AI_SCENE_FLAGS_NON_VERBOSE_FORMAT 0x8
|
||||
|
||||
/** @def AI_SCENE_FLAGS_TERRAIN
|
||||
/**
|
||||
* Denotes pure height-map terrain data. Pure terrains usually consist of quads,
|
||||
* sometimes triangles, in a regular grid. The x,y coordinates of all vertex
|
||||
* positions refer to the x,y coordinates on the terrain height map, the z-axis
|
||||
|
|
|
@ -241,7 +241,7 @@ struct aiColor3D
|
|||
* For most applications, it will be absolutely sufficient to interpret the
|
||||
* aiString as ASCII data and work with it as one would work with a plain char*.
|
||||
* Windows users in need of proper support for i.e asian characters can use the
|
||||
* #MultiByteToWideChar(), #WideCharToMultiByte() WinAPI functionality to convert the
|
||||
* MultiByteToWideChar(), WideCharToMultiByte() WinAPI functionality to convert the
|
||||
* UTF-8 strings to their working character set (i.e. MBCS, WideChar).
|
||||
*
|
||||
* We use this representation instead of std::string to be C-compatible. The
|
||||
|
@ -388,6 +388,8 @@ typedef enum aiReturn
|
|||
* Force 32-bit size enum
|
||||
*/
|
||||
_AI_ENFORCE_ENUM_SIZE = 0x7fffffff
|
||||
|
||||
/// @endcond
|
||||
} aiReturn; // !enum aiReturn
|
||||
|
||||
// just for backwards compatibility, don't use these constants anymore
|
||||
|
@ -414,13 +416,14 @@ enum aiOrigin
|
|||
* Force 32-bit size enum
|
||||
*/
|
||||
_AI_ORIGIN_ENFORCE_ENUM_SIZE = 0x7fffffff
|
||||
|
||||
/// @endcond
|
||||
}; // !enum aiOrigin
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
/** @brief Enumerates predefined log streaming destinations.
|
||||
* Logging to these streams can be enabled with a single call to
|
||||
* #LogStream::createDefaultStream or #aiAttachPredefinedLogStream(),
|
||||
* respectively.
|
||||
* #LogStream::createDefaultStream.
|
||||
*/
|
||||
enum aiDefaultLogStream
|
||||
{
|
||||
|
@ -442,6 +445,7 @@ enum aiDefaultLogStream
|
|||
* Force 32-bit size enum
|
||||
*/
|
||||
_AI_DLS_ENFORCE_ENUM_SIZE = 0x7fffffff
|
||||
/// @endcond
|
||||
}; // !enum aiDefaultLogStream
|
||||
|
||||
// just for backwards compatibility, don't use these constants anymore
|
||||
|
|
|
@ -38,7 +38,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
/** @file aiVector2t.h
|
||||
/** @file vector2.h
|
||||
* @brief 2D vector structure, including operators when compiling in C++
|
||||
*/
|
||||
#ifndef AI_VECTOR2D_H_INC
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiVector2D.inl
|
||||
/** @file vector2.inl
|
||||
* @brief Inline implementation of aiVector2t<TReal> operators
|
||||
*/
|
||||
#ifndef AI_VECTOR2D_INL_INC
|
||||
|
|
|
@ -38,7 +38,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
/** @file aiVector3D.h
|
||||
/** @file vector3.h
|
||||
* @brief 3D vector structure, including operators when compiling in C++
|
||||
*/
|
||||
#ifndef AI_VECTOR3D_H_INC
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiVector3D.inl
|
||||
/** @file vector3.inl
|
||||
* @brief Inline implementation of aiVector3t<TReal> operators
|
||||
*/
|
||||
#ifndef AI_VECTOR3D_INL_INC
|
||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file aiVersion.h
|
||||
/** @file version.h
|
||||
* @brief Functions to query the version of the Assimp runtime, check
|
||||
* compile flags, ...
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,754 @@
|
|||
ply
|
||||
format ascii 1.0
|
||||
element vertex 486
|
||||
property float32 x
|
||||
property float32 y
|
||||
property float32 z
|
||||
element face 912
|
||||
property list uint8 int32 vertex_indices
|
||||
end_header
|
||||
-1.106 3.844 9.073
|
||||
-0.3523 0.4402 11.07
|
||||
1.028 3.76 9.209
|
||||
0.137 -0.5632 10.73
|
||||
2.01 4.503 5.887
|
||||
0.07813 5.232 6.794
|
||||
-0.7266 3.741 3.839
|
||||
-2.789 3.179 5.07
|
||||
-0.9185 2.402 3.279
|
||||
1.445 2.139 3.394
|
||||
-3.114 1.498 5.285
|
||||
-1.317 -1.269 8.385
|
||||
-0.854 -1.319 5.036
|
||||
-0.9351 5.347 0.6162
|
||||
-0.8184 2.622 3.235
|
||||
0.4875 5.529 -0.2241
|
||||
3.193 2.756 1.633
|
||||
3.213 1.145 -2.568
|
||||
-2.25 1.208 2.767
|
||||
0.3225 0.8339 3.323
|
||||
1.354 -1.725 1.105
|
||||
0.1887 1.133 -5.785
|
||||
-3.637 2.696 0.3325
|
||||
-3.706 0.8936 -0.5452
|
||||
-0.4326 -0.8737 -4.095
|
||||
-2.994 -0.4858 0.9023
|
||||
0.1252 -2.079 -1.51
|
||||
2.856 -0.7459 -1.187
|
||||
2.32 3.733 8.13
|
||||
2.031 3.721 9.095
|
||||
2.819 3.567 8.537
|
||||
1.994 2.581 9.711
|
||||
2.64 2.491 9.542
|
||||
3.187 2.528 8.375
|
||||
1.628 2.491 7.518
|
||||
1.62 3.721 8.274
|
||||
0.9868 2.471 8.914
|
||||
1.552 2.106 9.414
|
||||
2.657 1.774 8.918
|
||||
-1.805 3.733 8.13
|
||||
-2.094 3.721 9.095
|
||||
-1.306 3.567 8.537
|
||||
-2.131 2.581 9.711
|
||||
-1.485 2.491 9.542
|
||||
-0.938 2.528 8.375
|
||||
-2.497 2.491 7.518
|
||||
-2.505 3.721 8.274
|
||||
-3.138 2.471 8.914
|
||||
-2.573 2.106 9.414
|
||||
-1.469 1.774 8.918
|
||||
1.549 3.638 6.803
|
||||
1.355 3.638 6.7
|
||||
1.424 5.126 6.883
|
||||
1.615 5.083 6.981
|
||||
1.169 3.638 6.815
|
||||
1.237 5.115 6.997
|
||||
1.176 3.638 7.035
|
||||
1.241 5.061 7.21
|
||||
1.369 3.638 7.138
|
||||
1.433 5.018 7.308
|
||||
1.556 3.638 7.023
|
||||
1.62 5.029 7.194
|
||||
1.625 6.512 7.421
|
||||
1.811 6.429 7.504
|
||||
1.437 6.49 7.531
|
||||
1.434 6.386 7.724
|
||||
1.619 6.304 7.807
|
||||
1.808 6.326 7.697
|
||||
1.945 7.702 8.276
|
||||
2.121 7.585 8.335
|
||||
1.754 7.672 8.38
|
||||
1.74 7.525 8.542
|
||||
1.916 7.408 8.601
|
||||
2.107 7.439 8.497
|
||||
2.362 8.615 9.391
|
||||
2.526 8.473 9.417
|
||||
2.168 8.578 9.487
|
||||
2.138 8.398 9.608
|
||||
2.303 8.255 9.635
|
||||
2.497 8.293 9.539
|
||||
2.847 9.189 10.69
|
||||
2.998 9.03 10.68
|
||||
2.649 9.148 10.78
|
||||
2.603 8.947 10.85
|
||||
2.753 8.788 10.84
|
||||
2.95 8.83 10.75
|
||||
3.368 9.385 12.08
|
||||
3.503 9.22 12.03
|
||||
3.167 9.342 12.16
|
||||
3.101 9.134 12.18
|
||||
3.236 8.97 12.13
|
||||
3.438 9.013 12.06
|
||||
3.889 9.189 13.48
|
||||
4.01 9.03 13.39
|
||||
3.684 9.148 13.54
|
||||
3.599 8.947 13.51
|
||||
3.719 8.788 13.42
|
||||
3.925 8.83 13.36
|
||||
4.374 8.615 14.77
|
||||
4.481 8.473 14.65
|
||||
4.165 8.578 14.83
|
||||
4.063 8.398 14.76
|
||||
4.17 8.255 14.63
|
||||
4.379 8.293 14.57
|
||||
4.791 7.702 15.89
|
||||
4.886 7.585 15.73
|
||||
4.579 7.672 15.94
|
||||
4.462 7.525 15.82
|
||||
4.556 7.408 15.66
|
||||
4.769 7.439 15.62
|
||||
5.111 6.512 16.74
|
||||
5.196 6.429 16.56
|
||||
4.896 6.49 16.78
|
||||
4.768 6.386 16.64
|
||||
4.853 6.304 16.46
|
||||
5.068 6.326 16.42
|
||||
-1.141 5.126 6.883
|
||||
-1.072 3.638 6.7
|
||||
-1.266 3.638 6.803
|
||||
-1.332 5.083 6.981
|
||||
-0.9541 5.115 6.997
|
||||
-0.886 3.638 6.815
|
||||
-0.9585 5.061 7.21
|
||||
-0.8928 3.638 7.035
|
||||
-1.15 5.018 7.308
|
||||
-1.086 3.638 7.138
|
||||
-1.337 5.029 7.194
|
||||
-1.272 3.638 7.023
|
||||
-1.342 6.512 7.421
|
||||
-1.528 6.429 7.504
|
||||
-1.154 6.49 7.531
|
||||
-1.151 6.386 7.724
|
||||
-1.336 6.304 7.807
|
||||
-1.525 6.326 7.697
|
||||
-1.662 7.702 8.276
|
||||
-1.838 7.585 8.335
|
||||
-1.471 7.672 8.38
|
||||
-1.457 7.525 8.542
|
||||
-1.633 7.408 8.601
|
||||
-1.824 7.439 8.497
|
||||
-2.079 8.615 9.391
|
||||
-2.243 8.473 9.417
|
||||
-1.885 8.578 9.487
|
||||
-1.855 8.398 9.608
|
||||
-2.02 8.255 9.635
|
||||
-2.214 8.293 9.539
|
||||
-2.564 9.189 10.69
|
||||
-2.715 9.03 10.68
|
||||
-2.366 9.148 10.78
|
||||
-2.32 8.947 10.85
|
||||
-2.47 8.788 10.84
|
||||
-2.667 8.83 10.75
|
||||
-3.085 9.385 12.08
|
||||
-3.22 9.22 12.03
|
||||
-2.884 9.342 12.16
|
||||
-2.818 9.134 12.18
|
||||
-2.953 8.97 12.13
|
||||
-3.155 9.013 12.06
|
||||
-3.606 9.189 13.48
|
||||
-3.726 9.03 13.39
|
||||
-3.4 9.148 13.54
|
||||
-3.316 8.947 13.51
|
||||
-3.437 8.788 13.42
|
||||
-3.642 8.83 13.36
|
||||
-4.091 8.615 14.77
|
||||
-4.198 8.473 14.65
|
||||
-3.882 8.578 14.83
|
||||
-3.78 8.398 14.76
|
||||
-3.887 8.255 14.63
|
||||
-4.096 8.293 14.57
|
||||
-4.508 7.702 15.89
|
||||
-4.603 7.585 15.73
|
||||
-4.296 7.672 15.94
|
||||
-4.179 7.525 15.82
|
||||
-4.273 7.408 15.66
|
||||
-4.485 7.439 15.62
|
||||
-4.828 6.512 16.74
|
||||
-4.913 6.429 16.56
|
||||
-4.613 6.49 16.78
|
||||
-4.484 6.386 16.64
|
||||
-4.57 6.304 16.46
|
||||
-4.784 6.326 16.42
|
||||
-1.519 -2.27 2.989
|
||||
-1.987 -1.082 3.408
|
||||
-2.709 -1.989 3.536
|
||||
-1.513 -2.259 2.974
|
||||
-2.524 -1.536 2.471
|
||||
-4.318 -0.3933 4.187
|
||||
-4.692 -0.6204 3.123
|
||||
-6.274 0.9227 4.173
|
||||
-5.533 1.852 4.043
|
||||
-6.084 1.387 3.082
|
||||
-6.844 2.279 4.015
|
||||
-6.83 1.957 4.012
|
||||
-6.886 2.118 3.737
|
||||
-7.536 1.346 4.658
|
||||
-7.229 0.9683 4.298
|
||||
-8.053 1.724 3.821
|
||||
-7.747 1.346 3.46
|
||||
-9.085 -0.1982 5.078
|
||||
-9.347 -0.1982 3.597
|
||||
-8.702 -0.7393 4.247
|
||||
-10.91 -1.528 5.154
|
||||
-10.39 -2.11 4.847
|
||||
-11.08 -1.528 4.148
|
||||
-10.49 -2.11 4.26
|
||||
-11.58 -2.509 4.768
|
||||
-11.57 -2.523 4.76
|
||||
-11.59 -2.509 4.742
|
||||
-11.57 -2.523 4.744
|
||||
-12.39 -3.546 5.269
|
||||
-11.93 -3.852 5.034
|
||||
-12.52 -3.546 4.548
|
||||
-12.87 -4.803 5.622
|
||||
-12.58 -5.09 4.606
|
||||
-13.49 -4.516 4.767
|
||||
-13.11 -6.264 5.38
|
||||
-14.78 -6.803 5.643
|
||||
-14.49 -7.092 4.622
|
||||
-15.35 -8.042 5.637
|
||||
-14.73 -8.43 5.528
|
||||
-15.15 -8.236 4.95
|
||||
-15.78 -9.378 5.503
|
||||
-15.77 -9.385 5.497
|
||||
-15.78 -9.375 5.495
|
||||
-15.78 -9.378 5.486
|
||||
-15.77 -9.383 5.484
|
||||
-1.522 -2.262 -1.24
|
||||
-1.519 -2.258 -1.231
|
||||
-1.522 -2.262 -1.222
|
||||
-1.529 -2.27 -1.222
|
||||
-1.529 -2.27 -1.24
|
||||
-2.061 -1.082 -0.8906
|
||||
-2.428 -1.536 -1.907
|
||||
-3.082 -0.4963 -0.5522
|
||||
-3.082 -0.4963 -1.91
|
||||
-3.759 -1.333 -1.628
|
||||
-5.567 0.1257 -0.8323
|
||||
-5.665 1.852 -0.8818
|
||||
-6.417 0.9227 -0.8818
|
||||
-6.041 1.387 -1.924
|
||||
-6.95 2.279 -1.137
|
||||
-6.937 1.957 -1.326
|
||||
-6.943 2.118 -1.418
|
||||
-7.378 0.9683 -0.9246
|
||||
-8.108 1.724 -0.9246
|
||||
-7.743 1.346 -1.84
|
||||
-8.797 0.8371 -0.6052
|
||||
-9.793 0.269 -1.611
|
||||
-8.891 -0.6654 -1.611
|
||||
-10.59 -2.11 -0.9326
|
||||
-10.57 -0.523 -0.8679
|
||||
-11.3 -1.375 -0.9326
|
||||
-10.94 -1.742 -1.823
|
||||
-11.75 -2.506 -1.223
|
||||
-11.73 -2.523 -1.223
|
||||
-11.74 -2.514 -1.247
|
||||
-12.76 -3.466 -1.017
|
||||
-12.14 -3.852 -1.017
|
||||
-12.45 -3.659 -1.656
|
||||
-13.16 -4.803 -0.6001
|
||||
-12.7 -5.09 -1.55
|
||||
-13.62 -4.516 -1.55
|
||||
-13.36 -6.264 -0.8809
|
||||
-15.05 -6.803 -0.9114
|
||||
-14.58 -7.092 -1.866
|
||||
-15.6 -8.042 -1.016
|
||||
-14.98 -8.43 -1.016
|
||||
-15.29 -8.236 -1.658
|
||||
-16.01 -9.378 -1.222
|
||||
-15.99 -9.385 -1.226
|
||||
-16.01 -9.375 -1.231
|
||||
-16.01 -9.378 -1.24
|
||||
-16 -9.383 -1.24
|
||||
-1.522 -2.27 -4.918
|
||||
-2.105 -1.082 -4.684
|
||||
-2.827 -1.989 -4.812
|
||||
-1.513 -2.262 -4.935
|
||||
-2.29 -1.536 -5.749
|
||||
-4.562 -0.3933 -4.75
|
||||
-4.55 -0.6204 -5.878
|
||||
-6.395 0.9227 -5.432
|
||||
-5.655 1.852 -5.302
|
||||
-5.844 1.387 -6.393
|
||||
-6.877 2.279 -5.776
|
||||
-6.863 1.957 -5.773
|
||||
-6.821 2.118 -6.051
|
||||
-7.747 1.346 -5.408
|
||||
-7.335 0.9683 -5.641
|
||||
-7.947 1.724 -6.372
|
||||
-7.536 1.346 -6.605
|
||||
-9.347 -0.1982 -5.543
|
||||
-9.085 -0.1982 -7.025
|
||||
-8.702 -0.7393 -6.193
|
||||
-11.08 -1.528 -6.095
|
||||
-10.49 -2.11 -6.206
|
||||
-10.91 -1.528 -7.101
|
||||
-10.39 -2.11 -6.794
|
||||
-11.59 -2.509 -6.689
|
||||
-11.57 -2.523 -6.691
|
||||
-11.58 -2.509 -6.715
|
||||
-11.57 -2.523 -6.707
|
||||
-12.52 -3.546 -6.495
|
||||
-12.01 -3.852 -6.559
|
||||
-12.39 -3.546 -7.217
|
||||
-13.09 -4.803 -6.326
|
||||
-12.47 -5.09 -7.18
|
||||
-13.38 -4.516 -7.341
|
||||
-13.24 -6.264 -6.637
|
||||
-14.89 -6.803 -6.96
|
||||
-14.27 -7.092 -7.819
|
||||
-15.42 -8.042 -7.159
|
||||
-14.8 -8.43 -7.051
|
||||
-15 -8.236 -7.738
|
||||
-15.78 -9.378 -7.432
|
||||
-15.77 -9.385 -7.434
|
||||
-15.78 -9.375 -7.442
|
||||
-15.78 -9.378 -7.45
|
||||
-15.77 -9.383 -7.448
|
||||
1.522 -2.27 -4.918
|
||||
1.511 -2.258 -4.926
|
||||
1.513 -2.262 -4.935
|
||||
2.828 -1.989 -4.812
|
||||
2.105 -1.082 -4.684
|
||||
2.29 -1.536 -5.749
|
||||
4.55 -0.6204 -5.878
|
||||
4.562 -0.3933 -4.75
|
||||
6.395 0.9227 -5.432
|
||||
5.655 1.852 -5.302
|
||||
5.844 1.387 -6.393
|
||||
6.877 2.279 -5.776
|
||||
6.863 1.957 -5.773
|
||||
6.821 2.118 -6.051
|
||||
7.335 0.9683 -5.641
|
||||
7.747 1.346 -5.408
|
||||
7.947 1.724 -6.372
|
||||
7.536 1.346 -6.605
|
||||
9.347 -0.1982 -5.543
|
||||
9.086 -0.1982 -7.025
|
||||
8.702 -0.7393 -6.193
|
||||
11.08 -1.528 -6.095
|
||||
10.49 -2.11 -6.206
|
||||
10.91 -1.528 -7.101
|
||||
10.39 -2.11 -6.794
|
||||
11.59 -2.509 -6.689
|
||||
11.57 -2.523 -6.691
|
||||
11.58 -2.509 -6.715
|
||||
11.57 -2.523 -6.707
|
||||
12.52 -3.546 -6.495
|
||||
12.01 -3.852 -6.559
|
||||
12.39 -3.546 -7.217
|
||||
12.47 -5.09 -7.18
|
||||
13.09 -4.803 -6.326
|
||||
13.38 -4.516 -7.341
|
||||
13.24 -6.264 -6.637
|
||||
14.89 -6.803 -6.96
|
||||
14.27 -7.092 -7.819
|
||||
15.42 -8.042 -7.159
|
||||
14.8 -8.43 -7.051
|
||||
15 -8.236 -7.738
|
||||
15.78 -9.378 -7.432
|
||||
15.77 -9.385 -7.434
|
||||
15.78 -9.375 -7.442
|
||||
15.78 -9.378 -7.45
|
||||
15.77 -9.383 -7.448
|
||||
-0.9592 -0.9547 10.35
|
||||
0.007813 0.3928 11.6
|
||||
-0.7324 1.062 10.63
|
||||
0.007813 -1.855 11.37
|
||||
0.007813 -2.459 10.63
|
||||
0.007813 0.3928 9.662
|
||||
-0.3928 1.509 10.63
|
||||
0.7327 1.062 10.63
|
||||
-0.007813 0.3928 11.6
|
||||
0.9595 -0.9547 10.35
|
||||
-0.007813 -1.855 11.37
|
||||
-0.007813 -2.459 10.63
|
||||
-0.007813 0.3928 9.662
|
||||
0.3931 1.509 10.63
|
||||
1.513 -2.262 2.988
|
||||
1.511 -2.258 2.979
|
||||
1.516 -2.262 2.97
|
||||
1.522 -2.27 2.971
|
||||
1.52 -2.27 2.989
|
||||
1.987 -1.082 3.408
|
||||
2.524 -1.536 2.471
|
||||
2.933 -0.4963 3.919
|
||||
3.168 -0.4963 2.581
|
||||
3.786 -1.333 2.977
|
||||
5.429 0.1257 4.074
|
||||
5.534 1.852 4.042
|
||||
6.274 0.9227 4.173
|
||||
6.085 1.387 3.082
|
||||
6.863 1.957 3.827
|
||||
6.844 2.279 4.015
|
||||
6.886 2.118 3.737
|
||||
7.229 0.9683 4.298
|
||||
7.947 1.724 4.425
|
||||
7.747 1.346 3.46
|
||||
8.57 0.8371 4.859
|
||||
9.726 0.269 4.042
|
||||
8.838 -0.6654 3.885
|
||||
10.39 -2.11 4.847
|
||||
10.37 -0.523 4.909
|
||||
11.09 -1.375 4.97
|
||||
10.89 -1.742 4.032
|
||||
11.59 -2.506 4.763
|
||||
11.57 -2.523 4.76
|
||||
11.58 -2.514 4.739
|
||||
12.55 -3.466 5.142
|
||||
11.93 -3.852 5.034
|
||||
12.35 -3.659 4.459
|
||||
12.58 -5.09 4.606
|
||||
12.87 -4.803 5.622
|
||||
13.49 -4.516 4.767
|
||||
13.11 -6.264 5.38
|
||||
14.78 -6.803 5.643
|
||||
14.49 -7.092 4.622
|
||||
15.35 -8.042 5.637
|
||||
14.73 -8.43 5.528
|
||||
15.15 -8.236 4.95
|
||||
15.78 -9.378 5.503
|
||||
15.77 -9.385 5.497
|
||||
15.78 -9.375 5.495
|
||||
15.78 -9.378 5.486
|
||||
15.77 -9.383 5.484
|
||||
1.529 -2.27 -1.222
|
||||
1.519 -2.258 -1.231
|
||||
1.522 -2.262 -1.24
|
||||
2.795 -1.989 -0.8906
|
||||
2.062 -1.082 -0.8906
|
||||
2.428 -1.536 -1.907
|
||||
4.677 -0.6204 -1.642
|
||||
4.493 -0.3933 -0.5283
|
||||
6.417 0.9227 -0.8818
|
||||
5.665 1.852 -0.8818
|
||||
6.041 1.387 -1.924
|
||||
6.951 2.279 -1.137
|
||||
6.937 1.957 -1.137
|
||||
6.944 2.118 -1.418
|
||||
7.379 0.9683 -0.9246
|
||||
7.743 1.346 -0.623
|
||||
8.108 1.724 -1.538
|
||||
7.743 1.346 -1.84
|
||||
9.343 -0.1982 -0.4792
|
||||
9.343 -0.1982 -1.983
|
||||
8.82 -0.7393 -1.231
|
||||
11.15 -1.528 -0.7207
|
||||
10.59 -2.11 -0.9326
|
||||
11.15 -1.528 -1.742
|
||||
10.59 -2.11 -1.53
|
||||
11.75 -2.509 -1.218
|
||||
11.73 -2.523 -1.223
|
||||
11.75 -2.509 -1.245
|
||||
11.73 -2.523 -1.239
|
||||
12.63 -3.546 -0.8647
|
||||
12.14 -3.852 -1.017
|
||||
12.63 -3.546 -1.598
|
||||
12.7 -5.09 -1.55
|
||||
13.16 -4.803 -0.6001
|
||||
13.62 -4.516 -1.55
|
||||
13.36 -6.264 -0.8804
|
||||
15.05 -6.803 -0.9111
|
||||
14.58 -7.092 -1.866
|
||||
15.6 -8.042 -1.016
|
||||
14.98 -8.43 -1.016
|
||||
15.29 -8.236 -1.658
|
||||
16.01 -9.378 -1.222
|
||||
15.99 -9.385 -1.226
|
||||
16.01 -9.375 -1.231
|
||||
16.01 -9.378 -1.24
|
||||
16 -9.383 -1.24
|
||||
-0.7932 4.462 -7.734
|
||||
-0.3843 1.974 -5.495
|
||||
1.95 3.241 -7.348
|
||||
1.167 0.6428 -6.109
|
||||
3.808 0.1871 -9.572
|
||||
3.644 1.688 -11.88
|
||||
0.07617 4.961 -10.12
|
||||
3.28 -0.5704 -14.15
|
||||
0.2488 -1.848 -16.78
|
||||
-0.9744 -2.686 -16.57
|
||||
0.7307 -3.159 -16.47
|
||||
-2.678 2.963 -8.185
|
||||
-2.616 -2.779 -12.24
|
||||
-1.159 -1.533 -8.922
|
||||
3 0 1 2
|
||||
3 1 3 2
|
||||
3 2 4 5
|
||||
3 4 6 5
|
||||
3 5 6 7
|
||||
3 7 6 8
|
||||
3 2 3 9
|
||||
3 2 9 4
|
||||
3 4 9 6
|
||||
3 6 9 8
|
||||
3 5 0 2
|
||||
3 5 7 0
|
||||
3 8 10 7
|
||||
3 7 10 0
|
||||
3 0 10 1
|
||||
3 1 10 11
|
||||
3 1 11 3
|
||||
3 10 12 11
|
||||
3 11 12 3
|
||||
3 3 12 9
|
||||
3 10 8 12
|
||||
3 12 8 9
|
||||
3 13 14 15
|
||||
3 15 14 16
|
||||
3 17 15 16
|
||||
3 18 19 14
|
||||
3 14 19 16
|
||||
3 19 20 16
|
||||
3 15 17 21
|
||||
3 15 21 13
|
||||
3 14 13 18
|
||||
3 21 22 13
|
||||
3 13 22 18
|
||||
3 21 23 22
|
||||
3 21 24 23
|
||||
3 23 25 22
|
||||
3 22 25 18
|
||||
3 18 25 20
|
||||
3 18 20 19
|
||||
3 23 26 25
|
||||
3 25 26 20
|
||||
3 23 24 26
|
||||
3 26 24 27
|
||||
3 26 27 20
|
||||
3 20 27 16
|
||||
3 24 21 27
|
||||
3 27 21 17
|
||||
3 27 17 16
|
||||
3 28 29 30
|
||||
3 31 32 29
|
||||
3 29 32 30
|
||||
3 32 33 30
|
||||
3 30 33 28
|
||||
3 28 33 34
|
||||
3 28 34 35
|
||||
3 35 34 36
|
||||
3 28 35 29
|
||||
3 35 36 29
|
||||
3 29 36 31
|
||||
3 36 37 31
|
||||
3 31 37 32
|
||||
3 37 38 32
|
||||
3 32 38 33
|
||||
3 36 34 37
|
||||
3 37 34 38
|
||||
3 38 34 33
|
||||
3 39 40 41
|
||||
3 42 43 40
|
||||
3 40 43 41
|
||||
3 43 44 41
|
||||
3 41 44 39
|
||||
3 39 44 45
|
||||
3 39 45 46
|
||||
3 46 45 47
|
||||
3 39 46 40
|
||||
3 46 47 40
|
||||
3 40 47 42
|
||||
3 47 48 42
|
||||
3 42 48 43
|
||||
3 48 49 43
|
||||
3 43 49 44
|
||||
3 47 45 48
|
||||
3 48 45 49
|
||||
3 49 45 44
|
||||
3 50 51 52
|
||||
3 50 52 53
|
||||
3 51 54 55
|
||||
3 51 55 52
|
||||
3 54 56 57
|
||||
3 54 57 55
|
||||
3 56 58 59
|
||||
3 56 59 57
|
||||
3 58 60 61
|
||||
3 58 61 59
|
||||
3 60 50 53
|
||||
3 60 53 61
|
||||
3 53 52 62
|
||||
3 53 62 63
|
||||
3 52 55 64
|
||||
3 52 64 62
|
||||
3 55 57 65
|
||||
3 55 65 64
|
||||
3 57 59 66
|
||||
3 57 66 65
|
||||
3 59 61 67
|
||||
3 59 67 66
|
||||
3 61 53 63
|
||||
3 61 63 67
|
||||
3 63 62 68
|
||||
3 63 68 69
|
||||
3 62 64 70
|
||||
3 62 70 68
|
||||
3 64 65 71
|
||||
3 64 71 70
|
||||
3 65 66 72
|
||||
3 65 72 71
|
||||
3 66 67 73
|
||||
3 66 73 72
|
||||
3 67 63 69
|
||||
3 67 69 73
|
||||
3 69 68 74
|
||||
3 69 74 75
|
||||
3 68 70 76
|
||||
3 68 76 74
|
||||
3 70 71 77
|
||||
3 70 77 76
|
||||
3 71 72 78
|
||||
3 71 78 77
|
||||
3 72 73 79
|
||||
3 72 79 78
|
||||
3 73 69 75
|
||||
3 73 75 79
|
||||
3 75 74 80
|
||||
3 75 80 81
|
||||
3 74 76 82
|
||||
3 74 82 80
|
||||
3 76 77 83
|
||||
3 76 83 82
|
||||
3 77 78 84
|
||||
3 77 84 83
|
||||
3 78 79 85
|
||||
3 78 85 84
|
||||
3 79 75 81
|
||||
3 79 81 85
|
||||
3 81 80 86
|
||||
3 81 86 87
|
||||
3 80 82 88
|
||||
3 80 88 86
|
||||
3 82 83 89
|
||||
3 82 89 88
|
||||
3 83 84 90
|
||||
3 83 90 89
|
||||
3 84 85 91
|
||||
3 84 91 90
|
||||
3 85 81 87
|
||||
3 85 87 91
|
||||
3 87 86 92
|
||||
3 87 92 93
|
||||
3 86 88 94
|
||||
3 86 94 92
|
||||
3 88 89 95
|
||||
3 88 95 94
|
||||
3 89 90 96
|
||||
3 89 96 95
|
||||
3 90 91 97
|
||||
3 90 97 96
|
||||
3 91 87 93
|
||||
3 91 93 97
|
||||
3 93 92 98
|
||||
3 93 98 99
|
||||
3 92 94 100
|
||||
3 92 100 98
|
||||
3 94 95 101
|
||||
3 94 101 100
|
||||
3 95 96 102
|
||||
3 95 102 101
|
||||
3 96 97 103
|
||||
3 96 103 102
|
||||
3 97 93 99
|
||||
3 97 99 103
|
||||
3 99 98 104
|
||||
3 99 104 105
|
||||
3 98 100 106
|
||||
3 98 106 104
|
||||
3 100 101 107
|
||||
3 100 107 106
|
||||
3 101 102 108
|
||||
3 101 108 107
|
||||
3 102 103 109
|
||||
3 102 109 108
|
||||
3 103 99 105
|
||||
3 103 105 109
|
||||
3 105 104 110
|
||||
3 105 110 111
|
||||
3 104 106 112
|
||||
3 104 112 110
|
||||
3 106 107 113
|
||||
3 106 113 112
|
||||
3 107 108 114
|
||||
3 107 114 113
|
||||
3 108 109 115
|
||||
3 108 115 114
|
||||
3 109 105 111
|
||||
3 109 111 115
|
||||
3 54 51 50
|
||||
3 56 54 50
|
||||
3 58 56 50
|
||||
3 60 58 50
|
||||
3 112 113 110
|
||||
3 113 114 110
|
||||
3 114 115 110
|
||||
3 115 111 110
|
||||
3 116 117 118
|
||||
3 119 116 118
|
||||
3 120 121 117
|
||||
3 116 120 117
|
||||
3 122 123 121
|
||||
3 120 122 121
|
||||
3 124 125 123
|
||||
3 122 124 123
|
||||
3 126 127 125
|
||||
3 124 126 125
|
||||
3 119 118 127
|
||||
3 126 119 127
|
||||
3 128 116 119
|
||||
3 129 128 119
|
||||
3 130 120 116
|
||||
3 128 130 116
|
||||
3 131 122 120
|
||||
3 130 131 120
|
||||
3 132 124 122
|
||||
3 131 132 122
|
||||
3 133 126 124
|
||||
3 132 133 124
|
||||
3 129 119 126
|
||||
3 133 129 126
|
||||
3 134 128 129
|
||||
3 135 134 129
|
||||
3 136 130 128
|
||||
3 134 136 128
|
||||
3 137 131 130
|
||||
3 136 137 130
|
||||
3 138 132 131
|
||||
3 137 138 131
|
||||
3 139 133 132
|
||||
3 138 139 132
|
||||
3 135 129 133
|
||||
3 139 135 133
|
||||
3 140 134 135
|
||||
3 141 140 135
|
||||
3 142 136 134
|
||||
3 140 142 134
|
||||
3 143 137 136
|
||||
3 142 143 136
|
||||
3 144 138 137
|
||||
3 143 144 137
|
||||
3 145 139 138
|
||||
3 144 145 138
|
||||
3 141 135 139
|
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
|
@ -221,7 +221,7 @@ public:
|
|||
private:
|
||||
|
||||
/* Report failure */
|
||||
void failure(const std::string& err, const std::string& name) {
|
||||
AI_WONT_RETURN void failure(const std::string& err, const std::string& name) AI_WONT_RETURN_SUFFIX {
|
||||
std::stringstream ss;
|
||||
throw compare_fails_exception((ss
|
||||
<< "Files are different at "
|
||||
|
|
Loading…
Reference in New Issue