Fix crashes induced by typeid

- implement virtual accessors in FarSubdivision tables that return a Scheme enum
- implement a safe typeid comparison in FarMeshFactory to get the same information
  from Hbr subdivision classes

fixes #240
This commit is contained in:
manuelk 2013-11-19 16:19:27 -08:00
parent fdfdb1cc8b
commit ab0cd0f8a2
6 changed files with 85 additions and 25 deletions

View File

@ -46,10 +46,15 @@ template <class U> class FarBilinearSubdivisionTables : public FarSubdivisionTab
public:
/// Returns the number of indexing tables needed to represent this particular
/// subdivision scheme.
/// \brief Returns the number of indexing tables needed to represent this
/// particular subdivision scheme.
virtual int GetNumTables() const { return 7; }
/// \brief Returns the subdivision scheme of the tables
virtual typename FarSubdivisionTables<U>::Scheme GetScheme() const {
return FarSubdivisionTables<U>::BILINEAR;
}
private:
template <class X, class Y> friend class FarBilinearSubdivisionTablesFactory;
template <class X, class Y> friend class FarMultiMeshFactory;

View File

@ -46,10 +46,15 @@ template <class U> class FarCatmarkSubdivisionTables : public FarSubdivisionTabl
public:
/// \brief Returns the number of indexing tables needed to represent this
/// \brief Returns the number of indexing tables needed to represent this
/// particular subdivision scheme.
virtual int GetNumTables() const { return 7; }
/// \brief Returns the subdivision scheme of the tables
virtual typename FarSubdivisionTables<U>::Scheme GetScheme() const {
return FarSubdivisionTables<U>::CATMARK;
}
private:
template <class X, class Y> friend class FarCatmarkSubdivisionTablesFactory;
template <class X, class Y> friend class FarMultiMeshFactory;

View File

@ -47,6 +47,11 @@ template <class U> class FarLoopSubdivisionTables : public FarSubdivisionTables<
public:
/// \brief Returns the subdivision scheme of the tables
virtual typename FarSubdivisionTables<U>::Scheme GetScheme() const {
return FarSubdivisionTables<U>::LOOP;
}
private:
template <class X, class Y> friend class FarLoopSubdivisionTablesFactory;
template <class X, class Y> friend class FarMultiMeshFactory;

View File

@ -171,6 +171,9 @@ private:
FarMeshFactory( FarMeshFactory const & );
FarMeshFactory<T,U> & operator=(FarMeshFactory<T,U> const &);
// True if t1 and t2 are the same, even accounting for plugins
static bool compareType(std::type_info const & t1, std::type_info const & t2);
// True if the HbrMesh applies the bilinear subdivision scheme
static bool isBilinear(HbrMesh<T> const * mesh);
@ -637,19 +640,37 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adapt
}
}
template <class T, class U> bool
FarMeshFactory<T,U>::compareType(std::type_info const & t1, std::type_info const & t2) {
if (t1==t2) {
return true;
}
// On some systems, distinct instances of \c type_info objects compare equal if
// their name() functions return equivalent strings. On other systems, distinct
// type_info objects never compare equal. The latter can cause problems in the
// presence of plugins loaded without RTLD_GLOBAL, because typeid(T) returns
// different \c type_info objects for the same T in the two plugins.
for (char const * p1 = t1.name(), *p2 = t2.name(); *p1 == *p2; ++p1, ++p2)
if (*p1 == '\0')
return true;
return false;
}
template <class T, class U> bool
FarMeshFactory<T,U>::isBilinear(HbrMesh<T> const * mesh) {
return typeid(*(mesh->GetSubdivision()))==typeid(HbrBilinearSubdivision<T>);
return compareType(typeid(*(mesh->GetSubdivision())), typeid(HbrBilinearSubdivision<T>));
}
template <class T, class U> bool
FarMeshFactory<T,U>::isCatmark(HbrMesh<T> const * mesh) {
return typeid(*(mesh->GetSubdivision()))==typeid(HbrCatmarkSubdivision<T>);
return compareType(typeid(*(mesh->GetSubdivision())), typeid(HbrCatmarkSubdivision<T>));
}
template <class T, class U> bool
FarMeshFactory<T,U>::isLoop(HbrMesh<T> const * mesh) {
return typeid(*(mesh->GetSubdivision()))==typeid(HbrLoopSubdivision<T>);
return compareType(typeid(*(mesh->GetSubdivision())), typeid(HbrLoopSubdivision<T>));
}
template <class T, class U> void

View File

@ -34,8 +34,6 @@
#include "../far/patchTablesFactory.h"
#include "../far/vertexEditTablesFactory.h"
#include <typeinfo>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
@ -101,7 +99,10 @@ FarMultiMeshFactory<T, U>::Create(std::vector<FarMesh<U> const *> const &meshes)
if (meshes.empty()) return NULL;
int totalFVarWidth = meshes[0]->GetTotalFVarWidth();
const std::type_info &scheme = typeid(*(meshes[0]->GetSubdivisionTables()));
typename FarSubdivisionTables<U>::Scheme scheme =
meshes[0]->GetSubdivisionTables()->GetScheme();
_maxlevel = 0;
_maxvalence = 0;
_isLoop = false;
@ -110,7 +111,7 @@ FarMultiMeshFactory<T, U>::Create(std::vector<FarMesh<U> const *> const &meshes)
FarMesh<U> const *mesh = meshes[i];
// meshes have to have a same subdivision scheme
if (scheme != typeid(*(mesh->GetSubdivisionTables()))) {
if (scheme != mesh->GetSubdivisionTables()->GetScheme()) {
assert(false);
return NULL;
}
@ -241,19 +242,26 @@ FarMultiMeshFactory<T, U>::spliceSubdivisionTables(FarMesh<U> *farMesh, FarMeshV
}
FarSubdivisionTables<U> *result = NULL;
const std::type_info &scheme = typeid(*(meshes[0]->GetSubdivisionTables()));
typename FarSubdivisionTables<U>::Scheme scheme =
meshes[0]->GetSubdivisionTables()->GetScheme();
if (scheme == typeid(FarCatmarkSubdivisionTables<U>) ) {
result = new FarCatmarkSubdivisionTables<U>(farMesh, _maxlevel);
_isLoop = false;
} else if (scheme == typeid(FarBilinearSubdivisionTables<U>) ) {
result = new FarBilinearSubdivisionTables<U>(farMesh, _maxlevel);
_isLoop = false;
} else if (scheme == typeid(FarLoopSubdivisionTables<U>) ) {
result = new FarLoopSubdivisionTables<U>(farMesh, _maxlevel);
_isLoop = true;
switch (scheme) {
case FarSubdivisionTables<U>::CATMARK:
result = new FarCatmarkSubdivisionTables<U>(farMesh, _maxlevel);
_isLoop = false;
break;
case FarSubdivisionTables<U>::LOOP:
result = new FarLoopSubdivisionTables<U>(farMesh, _maxlevel);
_isLoop = true;
break;
case FarSubdivisionTables<U>::BILINEAR:
result = new FarBilinearSubdivisionTables<U>(farMesh, _maxlevel);
_isLoop = false;
break;
default:
assert(0);
}
result->_F_ITa.resize(total_F_ITa);
result->_F_IT.resize(total_F_IT);
result->_E_IT.resize(total_E_IT);
@ -293,11 +301,13 @@ FarMultiMeshFactory<T, U>::spliceSubdivisionTables(FarMesh<U> *farMesh, FarMeshV
fvOffset += (int)tables->Get_F_ITa().size()/2;
V_IToffset += (int)tables->Get_V_IT().size();
if (scheme == typeid(FarCatmarkSubdivisionTables<U>) ||
scheme == typeid(FarLoopSubdivisionTables<U>)) {
if (scheme == FarSubdivisionTables<U>::CATMARK or
scheme == FarSubdivisionTables<U>::LOOP) {
evOffset += (int)tables->Get_E_IT().size()/4;
vvOffset += (int)tables->Get_V_ITa().size()/5;
} else {
evOffset += (int)tables->Get_E_IT().size()/2;
vvOffset += (int)tables->Get_V_ITa().size();
}
@ -335,10 +345,12 @@ FarMultiMeshFactory<T, U>::spliceSubdivisionTables(FarMesh<U> *farMesh, FarMeshV
E_W = copyWithOffset(E_W, tables->Get_E_W(), 0);
// copy vert tables
if (scheme == typeid(FarCatmarkSubdivisionTables<U>) ||
scheme == typeid(FarLoopSubdivisionTables<U>)) {
if (scheme == FarSubdivisionTables<U>::CATMARK or
scheme == FarSubdivisionTables<U>::LOOP) {
V_ITa = copyWithOffsetV_ITa(V_ITa, tables->Get_V_ITa(), V_IToffsets[i], vertexOffsets[i]);
} else {
V_ITa = copyWithOffset(V_ITa, tables->Get_V_ITa(), vertexOffsets[i]);
}
V_W = copyWithOffset(V_W, tables->Get_V_W(), 0);

View File

@ -65,6 +65,14 @@ template <class U> class FarMesh;
template <class U> class FarSubdivisionTables {
public:
enum Scheme {
UNDEFINED=0,
BILINEAR,
CATMARK,
LOOP
};
enum TableType {
E_IT, ///< edge-vertices adjacency indexing table
E_W, ///< edge-vertices weights
@ -128,6 +136,10 @@ public:
/// \brief Returns the vertex vertices weights table
std::vector<float> const & Get_V_W() const { return _V_W; }
/// \brief Returns the subdivision scheme of the tables
/// (sidesteps typeinfo dependency)
virtual Scheme GetScheme() const { return UNDEFINED; }
/// \brief Returns the number of indexing tables needed to represent this particular
/// subdivision scheme.
virtual int GetNumTables() const { return 5; }