Merge commit '87a0e7703258576f1a7e4ba763b961da70c1cd91' into contrib

Conflicts:
	code/ColladaExporter.cpp
This commit is contained in:
Léo Terziman
2014-01-17 11:19:29 +01:00
37 changed files with 1716 additions and 1197 deletions

View File

@@ -73,6 +73,7 @@ ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
}
SceneCombiner::CopyScene(pOut,pIn,true);
ScenePriv(*pOut)->mIsCopy = true;
}

View File

@@ -278,19 +278,23 @@ public:
// --------------------------------------------------------
// field parsing for pointer or dynamic array types
// (boost::shared_ptr or boost::shared_array)
// The return value indicates whether the data was already cached.
template <int error_policy, template <typename> class TOUT, typename T>
void ReadFieldPtr(TOUT<T>& out, const char* name,
const FileDatabase& db) const;
bool ReadFieldPtr(TOUT<T>& out, const char* name,
const FileDatabase& db,
bool non_recursive = false) const;
// --------------------------------------------------------
// field parsing for static arrays of pointer or dynamic
// array types (boost::shared_ptr[] or boost::shared_array[])
// The return value indicates whether the data was already cached.
template <int error_policy, template <typename> class TOUT, typename T, size_t N>
void ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
const FileDatabase& db) const;
// --------------------------------------------------------
// field parsing for `normal` values
// The return value indicates whether the data was already cached.
template <int error_policy, typename T>
void ReadField(T& out, const char* name,
const FileDatabase& db) const;
@@ -299,17 +303,18 @@ private:
// --------------------------------------------------------
template <template <typename> class TOUT, typename T>
void ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
const FileDatabase& db, const Field& f) const;
bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
const FileDatabase& db, const Field& f,
bool non_recursive = false) const;
// --------------------------------------------------------
template <template <typename> class TOUT, typename T>
void ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
const FileDatabase& db, const Field& f) const;
bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
const FileDatabase& db, const Field& f, bool) const;
// --------------------------------------------------------
void ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
const FileDatabase& db, const Field& f) const;
bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
const FileDatabase& db, const Field& f, bool) const;
// --------------------------------------------------------
inline const FileBlockHead* LocateFileBlockForAddress(
@@ -384,10 +389,11 @@ template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
};
// -------------------------------------------------------------------------------------------------------
template <> inline void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
const Pointer & ptrval,
const FileDatabase& db,
const Field& f
const Field& f,
bool
) const;

View File

@@ -180,7 +180,8 @@ void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileD
//--------------------------------------------------------------------------------
template <int error_policy, template <typename> class TOUT, typename T>
void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db) const
bool Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db,
bool non_recursive /*= false*/) const
{
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
Pointer ptrval;
@@ -203,23 +204,27 @@ void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabas
_defaultInitializer<error_policy>()(out,e.what());
out.reset();
return;
return false;
}
// resolve the pointer and load the corresponding structure
ResolvePointer(out,ptrval,db,*f);
const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
// and recover the previous stream position
db.reader->SetCurrentPos(old);
if(!non_recursive) {
// and recover the previous stream position
db.reader->SetCurrentPos(old);
}
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().fields_read;
#endif
return res;
}
//--------------------------------------------------------------------------------
template <int error_policy, template <typename> class TOUT, typename T, size_t N>
void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
const FileDatabase& db) const
{
// XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
@@ -253,11 +258,13 @@ void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
for(size_t i = 0; i < N; ++i) {
out[i].reset();
}
return;
return false;
}
bool res = true;
for(size_t i = 0; i < N; ++i) {
// resolve the pointer and load the corresponding structure
ResolvePointer(out[i],ptrval[i],db,*f);
res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
}
// and recover the previous stream position
@@ -266,6 +273,7 @@ void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().fields_read;
#endif
return res;
}
//--------------------------------------------------------------------------------
@@ -296,11 +304,13 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
//--------------------------------------------------------------------------------
template <template <typename> class TOUT, typename T>
void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const
bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
const Field& f,
bool non_recursive /*= false*/) const
{
out.reset();
out.reset(); // ensure null pointers work
if (!ptrval.val) {
return;
return false;
}
const Structure& s = db.dna[f.type];
// find the file block the pointer is pointing to
@@ -318,7 +328,7 @@ void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
// try to retrieve the object from the cache
db.cache(out).get(s,out,ptrval);
if (out) {
return;
return true;
}
// seek to this location, but save the previous stream pointer.
@@ -334,27 +344,36 @@ void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
// cache the object before we convert it to avoid cyclic recursion.
db.cache(out).set(s,out,ptrval);
for (size_t i = 0; i < num; ++i,++o) {
s.Convert(*o,db);
}
// if the non_recursive flag is set, we don't do anything but leave
// the cursor at the correct position to resolve the object.
if (!non_recursive) {
for (size_t i = 0; i < num; ++i,++o) {
s.Convert(*o,db);
}
db.reader->SetCurrentPos(pold);
db.reader->SetCurrentPos(pold);
}
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
if(out) {
++db.stats().pointers_resolved;
}
#endif
return false;
}
//--------------------------------------------------------------------------------
inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, const FileDatabase& db, const Field& /*f*/) const
inline bool Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
const FileDatabase& db,
const Field&,
bool) const
{
// Currently used exclusively by PackedFile::data to represent
// a simple offset into the mapped BLEND file.
out.reset();
if (!ptrval.val) {
return;
return false;
}
// find the file block the pointer is pointing to
@@ -362,11 +381,15 @@ inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, c
out = boost::shared_ptr< FileOffset > (new FileOffset());
out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
return false;
}
//--------------------------------------------------------------------------------
template <template <typename> class TOUT, typename T>
void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const
bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
const FileDatabase& db,
const Field& f,
bool) const
{
// This is a function overload, not a template specialization. According to
// the partial ordering rules, it should be selected by the compiler
@@ -374,7 +397,7 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
out.reset();
if (!ptrval.val) {
return;
return false;
}
// find the file block the pointer is pointing to
@@ -385,6 +408,7 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
bool res = false;
// allocate raw storage for the array
out.resize(num);
for (size_t i = 0; i< num; ++i) {
@@ -392,17 +416,19 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
Convert(val,db);
// and resolve the pointees
ResolvePointer(out[i],val,db,f);
res = ResolvePointer(out[i],val,db,f) && res;
}
db.reader->SetCurrentPos(pold);
return res;
}
//--------------------------------------------------------------------------------
template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
template <> bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
const Pointer & ptrval,
const FileDatabase& db,
const Field& /*f*/
const Field&,
bool
) const
{
// Special case when the data type needs to be determined at runtime.
@@ -410,7 +436,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
out.reset();
if (!ptrval.val) {
return;
return false;
}
// find the file block the pointer is pointing to
@@ -422,7 +448,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
// try to retrieve the object from the cache
db.cache(out).get(s,out,ptrval);
if (out) {
return;
return true;
}
// seek to this location, but save the previous stream pointer.
@@ -440,7 +466,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
DefaultLogger::get()->warn((Formatter::format(),
"Failed to find a converter for the `",s.name,"` structure"
));
return;
return false;
}
// allocate the object hull
@@ -459,11 +485,11 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
// to perform additional type checking.
out->dna_type = s.name.c_str();
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().pointers_resolved;
#endif
return false;
}
//--------------------------------------------------------------------------------

View File

@@ -446,9 +446,43 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
else {
name = aiString( img->name );
}
out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
conv_data.next_texture[aiTextureType_DIFFUSE]++)
);
aiTextureType texture_type = aiTextureType_UNKNOWN;
MTex::MapType map_type = tex->mapto;
if (map_type & MTex::MapType_COL)
texture_type = aiTextureType_DIFFUSE;
else if (map_type & MTex::MapType_NORM) {
if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
texture_type = aiTextureType_NORMALS;
}
else {
texture_type = aiTextureType_HEIGHT;
}
out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING);
}
else if (map_type & MTex::MapType_COLSPEC)
texture_type = aiTextureType_SPECULAR;
else if (map_type & MTex::MapType_COLMIR)
texture_type = aiTextureType_REFLECTION;
//else if (map_type & MTex::MapType_REF)
else if (map_type & MTex::MapType_SPEC)
texture_type = aiTextureType_SHININESS;
else if (map_type & MTex::MapType_EMIT)
texture_type = aiTextureType_EMISSIVE;
//else if (map_type & MTex::MapType_ALPHA)
//else if (map_type & MTex::MapType_HAR)
//else if (map_type & MTex::MapType_RAYMIRR)
//else if (map_type & MTex::MapType_TRANSLU)
else if (map_type & MTex::MapType_AMB)
texture_type = aiTextureType_AMBIENT;
else if (map_type & MTex::MapType_DISPLACE)
texture_type = aiTextureType_DISPLACEMENT;
//else if (map_type & MTex::MapType_WARP)
out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type,
conv_data.next_texture[texture_type]++));
}
// ------------------------------------------------------------------------------------------------
@@ -958,19 +992,41 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
}
// ------------------------------------------------------------------------------------------------
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* /*obj*/, const Camera* /*mesh*/, ConversionData& /*conv_data*/)
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
{
ScopeGuard<aiCamera> out(new aiCamera());
return NULL ; //out.dismiss();
out->mName = obj->id.name+2;
out->mPosition = aiVector3D(0.f, 0.f, 0.f);
out->mUp = aiVector3D(0.f, 1.f, 0.f);
out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
return out.dismiss();
}
// ------------------------------------------------------------------------------------------------
aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* /*obj*/, const Lamp* /*mesh*/, ConversionData& /*conv_data*/)
aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
{
ScopeGuard<aiLight> out(new aiLight());
out->mName = obj->id.name+2;
return NULL ; //out.dismiss();
switch (lamp->type)
{
case Lamp::Type_Local:
out->mType = aiLightSource_POINT;
break;
case Lamp::Type_Sun:
out->mType = aiLightSource_DIRECTIONAL;
// blender orients directional lights as facing toward -z
out->mDirection = aiVector3D(0.f, 0.f, -1.f);
break;
default:
break;
}
out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
return out.dismiss();
}
// ------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -598,6 +598,18 @@ struct Tex : ElemBase {
,Type_VOXELDATA = 15
};
enum ImageFlags {
ImageFlags_INTERPOL = 1
,ImageFlags_USEALPHA = 2
,ImageFlags_MIPMAP = 4
,ImageFlags_IMAROT = 16
,ImageFlags_CALCALPHA = 32
,ImageFlags_NORMALMAP = 2048
,ImageFlags_GAUSS_MIP = 4096
,ImageFlags_FILTER_MIN = 8192
,ImageFlags_DERIVATIVEMAP = 16384
};
ID id FAIL;
// AnimData *adt;
@@ -618,7 +630,8 @@ struct Tex : ElemBase {
//short noisedepth, noisetype;
//short noisebasis, noisebasis2;
//short imaflag, flag;
//short flag;
ImageFlags imaflag;
Type type FAIL;
//short stype;
@@ -685,7 +698,25 @@ struct MTex : ElemBase {
,BlendType_BLEND_COLOR = 13
};
// short texco, mapto, maptoneg;
enum MapType {
MapType_COL = 1
,MapType_NORM = 2
,MapType_COLSPEC = 4
,MapType_COLMIR = 8
,MapType_REF = 16
,MapType_SPEC = 32
,MapType_EMIT = 64
,MapType_ALPHA = 128
,MapType_HAR = 256
,MapType_RAYMIRR = 512
,MapType_TRANSLU = 1024
,MapType_AMB = 2048
,MapType_DISPLACE = 4096
,MapType_WARP = 8192
};
// short texco, maptoneg;
MapType mapto;
BlendType blendtype;
boost::shared_ptr<Object> object;
@@ -705,7 +736,8 @@ struct MTex : ElemBase {
//float colfac, varfac;
//float norfac, dispfac, warpfac;
float norfac;
//float dispfac, warpfac;
float colspecfac, mirrfac, alphafac;
float difffac, specfac, emitfac, hardfac;
//float raymirrfac, translfac, ambfac;

View File

@@ -47,204 +47,204 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace Blender {
template <> void Structure :: Convert<Object> (
Object& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Group> (
Group& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MTex> (
MTex& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<TFace> (
TFace& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<SubsurfModifierData> (
SubsurfModifierData& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MFace> (
MFace& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Lamp> (
Lamp& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MDeformWeight> (
MDeformWeight& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<PackedFile> (
PackedFile& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Base> (
Base& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MTFace> (
MTFace& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Material> (
Material& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MTexPoly> (
MTexPoly& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Mesh> (
Mesh& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MDeformVert> (
MDeformVert& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<World> (
World& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MLoopCol> (
MLoopCol& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MVert> (
MVert& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MEdge> (
MEdge& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MLoopUV> (
MLoopUV& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<GroupObject> (
GroupObject& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<ListBase> (
ListBase& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MLoop> (
MLoop& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<ModifierData> (
ModifierData& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<ID> (
ID& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MCol> (
MCol& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MPoly> (
MPoly& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Scene> (
Scene& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Library> (
Library& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Tex> (
Tex& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Camera> (
Camera& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MirrorModifierData> (
MirrorModifierData& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Image> (
Image& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Object> (
Object& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Group> (
Group& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MTex> (
MTex& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<TFace> (
TFace& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<SubsurfModifierData> (
SubsurfModifierData& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MFace> (
MFace& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Lamp> (
Lamp& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MDeformWeight> (
MDeformWeight& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<PackedFile> (
PackedFile& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Base> (
Base& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MTFace> (
MTFace& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Material> (
Material& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MTexPoly> (
MTexPoly& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Mesh> (
Mesh& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MDeformVert> (
MDeformVert& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<World> (
World& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MLoopCol> (
MLoopCol& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MVert> (
MVert& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MEdge> (
MEdge& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MLoopUV> (
MLoopUV& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<GroupObject> (
GroupObject& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<ListBase> (
ListBase& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MLoop> (
MLoop& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<ModifierData> (
ModifierData& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<ID> (
ID& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MCol> (
MCol& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MPoly> (
MPoly& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Scene> (
Scene& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Library> (
Library& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Tex> (
Tex& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Camera> (
Camera& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MirrorModifierData> (
MirrorModifierData& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<Image> (
Image& dest,
const FileDatabase& db
) const
;
}

View File

@@ -311,16 +311,15 @@ void ColladaExporter::WriteMaterials()
aiString name;
if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS )
name = "mat";
if(material_names.find(name.C_Str()) != material_names.end()) {
materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + "_" + name.C_Str();
material_names.insert(materials[a].name);
} else {
materials[a].name = name.C_Str();
}
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it )
if( !isalnum( *it) )
name = "mat";
materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
// of char to signed int and take the unsigned char value.
if( !isalnum( static_cast<uint8_t>(*it) ) ) {
*it = '_';
}
}
aiShadingMode shading;
materials[a].shading_model = "phong";

View File

@@ -88,7 +88,7 @@ Exporter::ExportFormatEntry gExporters[] =
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
aiProcess_GenNormals /*| aiProcess_PreTransformVertices */),
aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),
#endif
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
@@ -227,11 +227,47 @@ const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const
}
// ------------------------------------------------------------------------------------------------
bool IsVerboseFormat(const aiMesh* mesh)
{
// avoid slow vector<bool> specialization
std::vector<unsigned int> seen(mesh->mNumVertices,0);
for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
const aiFace& f = mesh->mFaces[i];
for(unsigned int j = 0; j < f.mNumIndices; ++j) {
if(++seen[f.mIndices[j]] == 2) {
// found a duplicate index
return false;
}
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
bool IsVerboseFormat(const aiScene* pScene)
{
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
if(!IsVerboseFormat(pScene->mMeshes[i])) {
return false;
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
{
ASSIMP_BEGIN_EXCEPTION_REGION();
// when they create scenes from scratch, users will likely create them not in verbose
// format. They will likely not be aware that there is a flag in the scene to indicate
// this, however. To avoid surprises and bug reports, we check for duplicates in
// meshes upfront.
const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
pimpl->mError = "";
for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
@@ -253,20 +289,21 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
// Erase all pp steps that were already applied to this scene
unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv
const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
? (priv->mPPStepsApplied & ~nonIdempotentSteps)
: 0u);
// If no extra postprocessing was specified, and we obtained this scene from an
// Assimp importer, apply the reverse steps automatically.
if (!pPreprocessing && priv) {
pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
}
// TODO: either drop this, or document it. Otherwise it is just a bad surprise.
//if (!pPreprocessing && priv) {
// pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
//}
// If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
// we need to run the MakeVerboseFormat step first.
bool must_join_again = false;
if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
if (!is_verbose_format) {
bool verbosify = false;
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {

View File

@@ -290,14 +290,19 @@ void Document::ReadHeader()
const Scope& shead = *ehead->Compound();
fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
if(fbxVersion < 7200 || fbxVersion > 7300) {
// while we maye have some success with newer files, we don't support
// the older 6.n fbx format
if(fbxVersion < 7200) {
DOMError("unsupported, old format version, supported are only FBX 2012 and FBX 2013");
}
if(fbxVersion > 7300) {
if(Settings().strictMode) {
DOMError("unsupported format version, supported are only FBX 2012 and FBX 2013"\
" in ASCII format (turn off strict mode to try anyhow) ");
DOMError("unsupported, newer format version, supported are only FBX 2012 and FBX 2013"
" (turn off strict mode to try anyhow) ");
}
else {
DOMWarning("unsupported format version, supported are only FBX 2012 and FBX 2013, trying to read it nevertheless");
DOMWarning("unsupported, newer format version, supported are only FBX 2012 and FBX 2013,"
" trying to read it nevertheless");
}
}

View File

@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
#include "IRRMeshLoader.h"
#include "ParsingUtils.h"
@@ -512,4 +512,4 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
AI_DEBUG_INVALIDATE_PTR(reader);
}
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
#endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER

View File

@@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
//This section should be excluded only if both the Irrlicht AND the Irrlicht Mesh importers were omitted.
#if !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
#include "IRRShared.h"
#include "ParsingUtils.h"
@@ -497,4 +498,4 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
return mat;
}
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
#endif // !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))

View File

@@ -1296,6 +1296,11 @@ void LWOImporter::LoadLWO2File()
uint8_t* const next = mFileBuffer+head->length;
unsigned int iUnnamed = 0;
if(!head->length) {
mFileBuffer = next;
continue;
}
switch (head->type)
{
// new layer

View File

@@ -167,19 +167,21 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
// The older LWOB format does not use indirect references to clips.
// The file name of a texture is directly specified in the tex chunk.
if (mIsLWO2) {
// find the corresponding clip
ClipList::iterator clip = mClips.begin();
// find the corresponding clip (take the last one if multiple
// share the same index)
ClipList::iterator end = mClips.end(), candidate = end;
temp = (*it).mClipIdx;
for (ClipList::iterator end = mClips.end(); clip != end; ++clip) {
if ((*clip).idx == temp)
break;
for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip) {
if ((*clip).idx == temp) {
candidate = clip;
}
}
if (mClips.end() == clip) {
if (candidate == end) {
DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
temp = 0;
// fixme: appearently some LWO files shipping with Doom3 don't
// fixme: apparently some LWO files shipping with Doom3 don't
// have clips at all ... check whether that's true or whether
// it's a bug in the loader.
@@ -188,16 +190,16 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
//continue;
}
else {
if (Clip::UNSUPPORTED == (*clip).type) {
if (Clip::UNSUPPORTED == (*candidate).type) {
DefaultLogger::get()->error("LWO2: Clip type is not supported");
continue;
}
AdjustTexturePath((*clip).path);
s.Set((*clip).path);
AdjustTexturePath((*candidate).path);
s.Set((*candidate).path);
// Additional image settings
int flags = 0;
if ((*clip).negate) {
if ((*candidate).negate) {
flags |= aiTextureFlags_Invert;
}
pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));

View File

@@ -61,14 +61,14 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
}
}
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
}
{
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
}
}
outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
}
}
@@ -199,6 +199,7 @@ void ObjExporter :: WriteGeometryFile()
AddNode(pScene->mRootNode,mBase);
// write vertex positions
vpMap.getVectors(vp);
mOutput << "# " << vp.size() << " vertex positions" << endl;
BOOST_FOREACH(const aiVector3D& v, vp) {
mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
@@ -206,6 +207,7 @@ void ObjExporter :: WriteGeometryFile()
mOutput << endl;
// write uv coordinates
vtMap.getVectors(vt);
mOutput << "# " << vt.size() << " UV coordinates" << endl;
BOOST_FOREACH(const aiVector3D& v, vt) {
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
@@ -213,6 +215,7 @@ void ObjExporter :: WriteGeometryFile()
mOutput << endl;
// write vertex normals
vnMap.getVectors(vn);
mOutput << "# " << vn.size() << " vertex normals" << endl;
BOOST_FOREACH(const aiVector3D& v, vn) {
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
@@ -252,6 +255,31 @@ void ObjExporter :: WriteGeometryFile()
}
}
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
{
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
if(vertIt != vecMap.end()){// vertex already exists, so reference it
return vertIt->second;
}
vecMap[vec] = mNextIndex;
int ret = mNextIndex;
mNextIndex++;
return ret;
}
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
{
vecs.resize(vecMap.size());
for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); it++){
vecs[it->second-1] = it->first;
}
}
// ------------------------------------------------------------------------------------------------
void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
{
@@ -262,6 +290,7 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
mesh.matname = GetMaterialName(m->mMaterialIndex);
mesh.faces.resize(m->mNumFaces);
for(unsigned int i = 0; i < m->mNumFaces; ++i) {
const aiFace& f = m->mFaces[i];
@@ -281,21 +310,22 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
const unsigned int idx = f.mIndices[a];
// XXX need a way to check if this is an unique vertex or if we had it already,
// in which case we should instead reference the previous occurrence.
ai_assert(m->mVertices);
vp.push_back( mat * m->mVertices[idx] );
face.indices[a].vp = vp.size();
aiVector3D vert = mat * m->mVertices[idx];
face.indices[a].vp = vpMap.getIndex(vert);
if (m->mNormals) {
vn.push_back( m->mNormals[idx] );
face.indices[a].vn = vnMap.getIndex(m->mNormals[idx]);
}
else{
face.indices[a].vn = 0;
}
face.indices[a].vn = vn.size();
if (m->mTextureCoords[0]) {
vt.push_back( m->mTextureCoords[0][idx] );
face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]);
}
else{
face.indices[a].vt = 0;
}
face.indices[a].vt = vt.size();
}
}
}

View File

@@ -112,6 +112,36 @@ private:
const aiScene* const pScene;
std::vector<aiVector3D> vp, vn, vt;
struct aiVectorCompare
{
bool operator() (const aiVector3D& a, const aiVector3D& b) const
{
if(a.x < b.x) return true;
if(a.x > b.x) return false;
if(a.y < b.y) return true;
if(a.y > b.y) return false;
if(a.z < b.z) return true;
return false;
}
};
class vecIndexMap
{
int mNextIndex;
typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
dataType vecMap;
public:
vecIndexMap():mNextIndex(1)
{}
int getIndex(const aiVector3D& vec);
void getVectors( std::vector<aiVector3D>& vecs );
};
vecIndexMap vpMap, vnMap, vtMap;
std::vector<MeshInstance> meshes;
// this endl() doesn't flush() the stream

View File

@@ -276,14 +276,23 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
{
ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
pMesh->mNumFaces += inp->m_pVertices->size() - 1;
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
}
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
pMesh->mNumFaces += inp->m_pVertices->size();
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
}
else {
++pMesh->mNumFaces;
if (inp->m_pVertices->size() > 3) {
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
}
else {
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
}
}
}
@@ -384,7 +393,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
// Copy all normals
if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty())
if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
{
const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
if ( normal >= pModel->m_Normals.size() )
@@ -394,21 +403,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
}
// Copy all texture coordinates
if ( !pModel->m_TextureCoord.empty() )
if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
{
if ( !pSourceFace->m_pTexturCoords->empty() )
{
const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
ai_assert( tex < pModel->m_TextureCoord.size() );
for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ )
{
if ( tex >= pModel->m_TextureCoord.size() )
throw DeadlyImportError("OBJ: texture coord index out of range");
const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
ai_assert( tex < pModel->m_TextureCoord.size() );
if ( tex >= pModel->m_TextureCoord.size() )
throw DeadlyImportError("OBJ: texture coord index out of range");
aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
}
}
aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
}
ai_assert( pMesh->mNumVertices > newIndex );
@@ -587,15 +591,12 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
// Assign parent to child
pChild->mParent = pParent;
size_t sNumChildren = 0;
(void)sNumChildren; // remove warning on release build
// If already children was assigned to the parent node, store them in a
std::vector<aiNode*> temp;
if (pParent->mChildren != NULL)
{
sNumChildren = pParent->mNumChildren;
ai_assert( 0 != sNumChildren );
ai_assert( 0 != pParent->mNumChildren );
for (size_t index = 0; index < pParent->mNumChildren; index++)
{
temp.push_back(pParent->mChildren [ index ] );

View File

@@ -77,7 +77,7 @@ public:
private:
//! \brief Appends the supported extention.
//! \brief Appends the supported extension.
const aiImporterDesc* GetInfo () const;
//! \brief File import implementation.
@@ -104,18 +104,15 @@ private:
//! \brief Material creation.
void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
//! \brief Appends a child node to a parentnode and updates the datastructures.
//! \brief Appends a child node to a parent node and updates the data structures.
void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
//! \brief TODO!
void createAnimations();
private:
//! Data buffer
std::vector<char> m_Buffer;
//! Pointer to root object instance
ObjFile::Object *m_pRootObject;
//! Absolute pathname of model in filesystem
//! Absolute pathname of model in file system
std::string m_strAbsPath;
};

View File

@@ -112,7 +112,7 @@ void ObjFileParser::parseFile()
case 'v': // Parse a vertex texture coordinate
{
++m_DataIt;
if (*m_DataIt == ' ')
if (*m_DataIt == ' ' || *m_DataIt == '\t')
{
// Read in vertex definition
getVector3(m_pModel->m_Vertices);
@@ -200,6 +200,8 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
break;
++m_DataIt;
}
ai_assert(index < length);
pBuffer[index] = '\0';
}
@@ -207,16 +209,30 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
// Copy the next line into a temporary buffer
void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
{
size_t index = 0;
while (m_DataIt != m_DataItEnd)
{
if (*m_DataIt == '\n' || *m_DataIt == '\r' || index == length-1)
break;
size_t index = 0u;
pBuffer[ index ] = *m_DataIt;
++index;
++m_DataIt;
// some OBJ files have line continuations using \ (such as in C++ et al)
bool continuation = false;
for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt)
{
const char c = *m_DataIt;
if (c == '\\') {
continuation = true;
continue;
}
if (c == '\n' || c == '\r') {
if(continuation) {
pBuffer[ index++ ] = ' ';
continue;
}
break;
}
continuation = false;
pBuffer[ index++ ] = c;
}
ai_assert(index < length);
pBuffer[ index ] = '\0';
}
@@ -274,6 +290,10 @@ void ObjFileParser::getFace(aiPrimitiveType type)
std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
bool hasNormal = false;
const int vSize = m_pModel->m_Vertices.size();
const int vtSize = m_pModel->m_TextureCoord.size();
const int vnSize = m_pModel->m_Normals.size();
const bool vt = (!m_pModel->m_TextureCoord.empty());
const bool vn = (!m_pModel->m_Normals.empty());
int iStep = 0, iPos = 0;
@@ -307,7 +327,11 @@ void ObjFileParser::getFace(aiPrimitiveType type)
{
//OBJ USES 1 Base ARRAYS!!!!
const int iVal = atoi( pPtr );
// increment iStep position based off of the sign and # of digits
int tmp = iVal;
if (iVal < 0)
++iStep;
while ( ( tmp = tmp / 10 )!=0 )
++iStep;
@@ -332,6 +356,27 @@ void ObjFileParser::getFace(aiPrimitiveType type)
reportErrorTokenInFace();
}
}
else if ( iVal < 0 )
{
// Store relatively index
if ( 0 == iPos )
{
pIndices->push_back( vSize + iVal );
}
else if ( 1 == iPos )
{
pTexID->push_back( vtSize + iVal );
}
else if ( 2 == iPos )
{
pNormalID->push_back( vnSize + iVal );
hasNormal = true;
}
else
{
reportErrorTokenInFace();
}
}
}
pPtr += iStep;
}

View File

@@ -103,7 +103,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
mOutput << "ply" << endl;
mOutput << "format ascii 1.0" << endl;
mOutput << "Created by Open Asset Import Library - http://assimp.sf.net (v"
mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v"
<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
<< aiGetVersionRevision() << ")" << endl;
@@ -159,7 +159,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
}
mOutput << "element face " << faces << endl;
mOutput << "property list uint uint vertex_indices" << endl;
mOutput << "property list uint uint vertex_index" << endl;
mOutput << "end_header" << endl;
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {

View File

@@ -86,7 +86,12 @@ bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
if (IsBinarySTL(buffer, fileSize))
return false;
if (fileSize < 5)
const char* bufferEnd = buffer + fileSize;
if (!SkipSpaces(&buffer))
return false;
if (buffer + 5 >= bufferEnd)
return false;
return strncmp(buffer, "solid", 5) == 0;
@@ -209,7 +214,11 @@ void STLImporter::LoadASCIIFile()
{
aiMesh* pMesh = pScene->mMeshes[0];
const char* sz = mBuffer + 5; // skip the "solid"
const char* sz = mBuffer;
SkipSpaces(&sz);
ai_assert(!IsLineEnd(sz));
sz += 5; // skip the "solid"
SkipSpaces(&sz);
const char* szMe = sz;
while (!::IsSpaceOrNewLine(*sz)) {

View File

@@ -53,6 +53,7 @@ struct ScenePrivateData {
ScenePrivateData()
: mOrigImporter()
, mPPStepsApplied()
, mIsCopy()
{}
// Importer that originally loaded the scene though the C-API
@@ -61,6 +62,13 @@ struct ScenePrivateData {
// List of postprocessing steps already applied to the scene.
unsigned int mPPStepsApplied;
// true if the scene is a copy made with aiCopyScene()
// or the corresponding C++ API. This means that user code
// may have made modifications to it, so mPPStepsApplied
// and mOrigImporter are no longer safe to rely on and only
// serve informative purposes.
bool mIsCopy;
};
// Access private data stored in the scene