Changes for supporting copying of PerVertex,PerEdge and PerFace attributes in the vcg::tri::Append (append.h)

- useless template paramtere in SimpleTempData_Base removed (simple_temporary_data.h)
- Attribute is now derived by SimpleTempData_Base
- SimpleTempData_Base defines a void * At(unsigned int i) function that returns a pointer to the i-th element of the vector withouth knowing the type
- removed the useless member _typeid from the PointerToAttribute. It was used to store the rtti, useless itself.

NOTE: the copy of attributes is done with a memcpy! This means that if you defined a operator = in your attribute this WILL NOT be used in the append.
This commit is contained in:
ganovelli 2011-06-01 13:39:31 +00:00
parent 7a86b3fd25
commit 11adfa2aff
4 changed files with 100 additions and 179 deletions

View File

@ -30,7 +30,6 @@
#include <string>
#include <set>
#include <assert.h>
#include <vcg/complex/complex.h>
#include <vcg/container/simple_temporary_data.h>
namespace vcg {
@ -903,10 +902,10 @@ public:
i = m.vert_attr.find(h);
assert(i ==m.vert_attr.end() );// an attribute with this name exists
}
h._typename = typeid(ATTR_TYPE).name();
h._sizeof = sizeof(ATTR_TYPE);
h._padding = 0;
h._handle = (void*) new SimpleTempData<VertContainer,ATTR_TYPE>(m.vert);
h._handle = new SimpleTempData<VertContainer,ATTR_TYPE>(m.vert);
m.attrn++;
h.n_attr = m.attrn;
std::pair < AttrIterator , bool> res = m.vert_attr.insert(h);
@ -974,7 +973,7 @@ public:
PointerToAttribute h1; h1._name = name;
i = m.vert_attr.find(h1);
assert(i!=m.vert_attr.end());
delete ((SimpleTempDataBase<VertContainer>*)(*i)._handle);
delete ((SimpleTempDataBase*)(*i)._handle);
m.vert_attr.erase(i);
}
@ -1062,7 +1061,7 @@ public:
PointerToAttribute h1; h1._name = name;
i = m.edge_attr.find(h1);
assert(i!=m.edge_attr.end());
delete ((SimpleTempDataBase<EdgeContainer>*)(*i)._handle);
delete ((SimpleTempDataBase*)(*i)._handle);
m.edge_attr.erase(i);
}
@ -1087,10 +1086,10 @@ public:
i = m.face_attr.find(h);
assert(i ==m.face_attr.end() );// an attribute with this name exists
}
h._typename = typeid(ATTR_TYPE).name();
h._sizeof = sizeof(ATTR_TYPE);
h._padding = 0;
h._handle = (void*) new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face);
h._handle = new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face);
m.attrn++;
h.n_attr = m.attrn;
std::pair < AttrIterator , bool> res = m.face_attr.insert(h);
@ -1155,7 +1154,7 @@ public:
PointerToAttribute h1; h1._name = name;
i = m.face_attr.find(h1);
assert(i!=m.face_attr.end());
delete ((SimpleTempDataBase<FaceContainer>*)(*i)._handle);
delete ((SimpleTempDataBase*)(*i)._handle);
m.face_attr.erase(i);
}
@ -1180,10 +1179,9 @@ public:
i = m.mesh_attr.find(h);
assert(i ==m.mesh_attr.end() );// an attribute with this name exists
}
h._typename = typeid(ATTR_TYPE).name();
h._sizeof = sizeof(ATTR_TYPE);
h._padding = 0;
h._handle = (void*) new Attribute<ATTR_TYPE>();
h._handle = new Attribute<ATTR_TYPE>();
m.attrn++;
h.n_attr = m.attrn;
std::pair < AttrIterator , bool> res = m.mesh_attr.insert(h);
@ -1243,7 +1241,7 @@ public:
PointerToAttribute h1; h1._name = name;
i = m.mesh_attr.find(h1);
assert(i!=m.mesh_attr.end());
delete ((AttributeBase *)(*i)._handle);
delete ((SimpleTempDataBase *)(*i)._handle);
m.mesh_attr.erase(i);
}
@ -1258,13 +1256,13 @@ public:
_handle->Resize(m.vert.size());
for(unsigned int i = 0; i < m.vert.size(); ++i){
ATTR_TYPE * dest = &(*_handle)[i];
char * ptr = (char*)( ((SimpleTempDataBase<VertContainer> *)pa._handle)->DataBegin());
char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin());
memcpy((void*)dest ,
(void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE));
}
// remove the padded container
delete ((SimpleTempDataBase<VertContainer>*) pa._handle);
delete ((SimpleTempDataBase*) pa._handle);
// update the pointer to data
pa._sizeof = sizeof(ATTR_TYPE);
@ -1287,13 +1285,13 @@ public:
_handle->Resize(m.face.size());
for(unsigned int i = 0; i < m.face.size(); ++i){
ATTR_TYPE * dest = &(*_handle)[i];
char * ptr = (char*)( ((SimpleTempDataBase<FaceContainer> *)pa._handle)->DataBegin());
char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin());
memcpy((void*)dest ,
(void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE));
}
// remove the padded container
delete ((SimpleTempDataBase<FaceContainer>*) pa._handle);
delete ((SimpleTempDataBase*) pa._handle);
// update the pointer to data
pa._sizeof = sizeof(ATTR_TYPE);
@ -1331,117 +1329,6 @@ public:
}
/* This section enables the calling of all allocating/deallocating functions just by attribute name,
without knowing the type
*/
// base class of all name type bound
struct NameTypeBound_Base{
virtual std::string Name() = 0;
virtual std::string TypeID() = 0;
template <class BoundMeshType>
void AddPerVertexAttribute(MeshType & m){assert(0);};
template <class BoundMeshType>
void AddPerFaceAttribute(MeshType & m){assert(0);};
template <class BoundMeshType>
void AddPerEdgeAttribute(MeshType & m){assert(0);};
template <class BoundMeshType>
void AddPerMeshAttribute(MeshType & m){assert(0);};
};
typedef typename std::map<std::string,NameTypeBound_Base*>::iterator BindersIterator;
typedef typename std::map<std::string,NameTypeBound_Base*>::const_iterator CBindersIterator;
typedef std::pair<std::string,NameTypeBound_Base*> TypeBound;
typedef std::map<std::string,NameTypeBound_Base*> NameTypeScope;
template <class TYPE>
struct NameTypeBound: public NameTypeBound_Base{
NameTypeBound(){}
NameTypeBound(std::string name){_name = name ;}
std::string Name() {return _name;}
bool operator ==(const NameTypeBound & o ) const {return Name()==o.Name();}
std::string TypeID(){ return typeid(TYPE).name();}
template <class BoundMeshType>
void AddPerVertexAttribute(BoundMeshType & m){Allocator<BoundMeshType>::template AddPerVertexAttribute<TYPE>(m,_name);}
template <class BoundMeshType>
void AddPerFaceAttribute(MeshType & m) {Allocator<BoundMeshType>::template AddPerFaceAttribute<TYPE> (m,_name);}
template <class BoundMeshType>
void AddPerEdgeAttribute(MeshType & m) {Allocator<BoundMeshType>::template AddPerEdgeAttribute<TYPE> (m,_name);}
template <class BoundMeshType>
void AddPerMeshAttribute(MeshType & m) {Allocator<BoundMeshType>::template AddPerMeshAttribute<TYPE> (m,_name);}
private:
std::string _name;
};
static bool CheckNameIsBound(const NameTypeScope & binders,std::string name){ return (binders.find(name)!=binders.end()); }
template <class TYPE>
static void AddNameTypeBound(NameTypeScope & binders,std::string name){
assert(!name.empty()); // you cannot bound a type to an empty string
BindersIterator bi = binders.find(name);
if(bi!=binders.end())
assert(typeid(TYPE).name() == ((*bi).second)->TypeID()); // the name was previously bound to a dirrefent type
else{
NameTypeBound<TYPE> * newbound = new NameTypeBound<TYPE>(name);
binders.insert( TypeBound(name,newbound));
}
}
static void RemoveTypeBound( NameTypeScope& binders,std::string name){
BindersIterator bi = binders.find(name);
if(bi!=binders.end()) {delete(*bi).second; binders.erase(bi);}
}
/* return the name of all the attributes of a given type */
template <typename TYPE>
static std::vector<std::string> NamesWithType(const NameTypeScope & binders){
std::vector<std::string> res;
CBindersIterator bi;
for(bi = binders.begin(); bi != binders.end(); ++bi)
if (typeid(TYPE).name() == ((*bi).second->TypeID()))
res.push_back( (*bi).second->Name());
return res;
}
static void AddPerVertexAttribute(const NameTypeScope & binders, MeshType & m, std::string name){
BindersIterator bi = binders.find(name);
assert(bi != binders.end() ); // the name MUST have been already bound to a type
(*bi).second->AddPerVertexAttribute(m);
}
static void AddPerEdgeAttribute(const NameTypeScope & binders, MeshType & m, std::string name){
BindersIterator bi = binders.find(name);
assert(bi != binders.end() ); // the name MUST have been already bound to a type
(*bi).second->AddPerEdgeAttribute(m);
}
static void AddPerFaceAttribute(const NameTypeScope & binders,MeshType & m, std::string name){
BindersIterator bi = binders.find(name);
assert(bi != binders.end() ); // the name MUST have been already bound to a type
(*bi).second->AddPerFaceAttribute(m);
}
static void AddPerMeshAttribute( const NameTypeScope & binders,MeshType & m, std::string name){
CBindersIterator bi = binders.find(name);
assert(bi != binders.end() ); // the name MUST have been already bound to a type
(*bi).second->AddPerMeshAttribute(m);
}
}; // end class

View File

@ -26,6 +26,7 @@
#include <vcg/complex/allocate.h>
#include <vcg/complex/algorithms/update/flag.h>
#include <set>
namespace vcg {
namespace tri {
@ -300,12 +301,59 @@ static void Mesh(MeshLeft& ml, MeshRight& mr, const bool selected = false){
// If the left mesh has attributes that are not in the right mesh, their values for the elements
// of the right mesh will be uninitialized
// to be done.
// note: we need to assign attribute values without knowing their type
unsigned int id_r;
typename std::set< typename MeshRight::PointerToAttribute >::iterator al,ar;
// per vertex attributes
for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al)
if(!(*al)._name.empty()){
ar = mr.vert_attr.find(*al);
if(ar!= mr.vert_attr.end()){
id_r = 0;
for(vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r)
if( !(*vi).IsD() && (!selected || (*vi).IsS()))
memcpy((*al)._handle->At(remap.vert[Index(mr,*vi)]),(*ar)._handle->At(id_r),
(*al)._handle->SizeOf());
}
}
// per edge attributes
for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al)
if(!(*al)._name.empty()){
ar = mr.edge_attr.find(*al);
if(ar!= mr.edge_attr.end()){
id_r = 0;
for(ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r)
if( !(*ei).IsD() && (!selected || (*ei).IsS()))
memcpy((*al)._handle->At(remap.vert[Index(mr,*ei)]),(*ar)._handle->At(id_r),
(*al)._handle->SizeOf());
}
}
// per face attributes
for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al)
if(!(*al)._name.empty()){
ar = mr.face_attr.find(*al);
if(ar!= mr.face_attr.end()){
id_r = 0;
for(fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r)
if( !(*fi).IsD() && (!selected || (*fi).IsS()))
memcpy((*al)._handle->At(remap.vert[Index(mr,*fi)]),(*ar)._handle->At(id_r),
(*al)._handle->SizeOf());
}
}
// per mesh attributes
// if both ml and mr have an attribute with the same name, no action is done
// if mr has an attribute that is NOT present in ml, the attribute is added to ml
//for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar)
// if(!(*ar)._name.empty()){
// al = ml.mesh_attr.find(*ar);
// if(al== ml.mesh_attr.end())
// //...
// }
}
static void Selected(MeshLeft& ml, MeshRight& mr)

View File

@ -39,7 +39,7 @@
#include <vcg/connectors/hedge.h>
#include <vcg/complex/used_types.h>
#include <vcg/container/derivation_chain.h>
#include <vcg/complex/allocate.h>
#ifndef __VCG_MESH
@ -224,15 +224,14 @@ class TriMesh
class PointerToAttribute{
public:
void * _handle; // pointer to the SimpleTempData that stores the attribute
SimpleTempDataBase * _handle; // pointer to the SimpleTempData that stores the attribute
std::string _name; // name of the attribute
std::string _typename; // name as returned by the rtti
int _sizeof; // size of the attribute type (used only with VMI loading)
int _padding; // padding (used only with VMI loading)
int n_attr; // unique ID of the attribute
void Resize(const int & sz){((SimpleTempDataBase<VertContainer>*)_handle)->Resize(sz);}
void Reorder(std::vector<size_t> & newVertIndex){((SimpleTempDataBase<VertContainer>*)_handle)->Reorder(newVertIndex);}
void Resize(const int & sz){((SimpleTempDataBase *)_handle)->Resize(sz);}
void Reorder(std::vector<size_t> & newVertIndex){((SimpleTempDataBase *)_handle)->Reorder(newVertIndex);}
bool operator<(const PointerToAttribute b) const { return(_name.empty()&&b._name.empty())?(_handle < b._handle):( _name < b._name);}
};
@ -242,12 +241,13 @@ class TriMesh
std::set< PointerToAttribute > mesh_attr;
template <class ATTR_TYPE, class CONT>
class AttributeHandle{
public:
AttributeHandle(){_handle=(SimpleTempData<CONT,ATTR_TYPE> *)NULL;}
AttributeHandle( void *ah,const int & n):_handle ( (SimpleTempData<CONT,ATTR_TYPE> *)ah ),n_attr(n){}
AttributeHandle operator = ( const CONT & pva){
AttributeHandle operator = ( const PointerToAttribute & pva){
_handle = (SimpleTempData<CONT,ATTR_TYPE> *)pva._handle;
n_attr = pva.n_attr;
return (*this);
@ -268,21 +268,21 @@ class TriMesh
class PerVertexAttributeHandle: public AttributeHandle<ATTR_TYPE,VertContainer>{
public:
PerVertexAttributeHandle():AttributeHandle<ATTR_TYPE,VertContainer>(){}
PerVertexAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,VertContainer>(ah,n){};
PerVertexAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,VertContainer>(ah,n){}
};
template <class ATTR_TYPE>
class PerFaceAttributeHandle: public AttributeHandle<ATTR_TYPE,FaceContainer>{
public:
PerFaceAttributeHandle():AttributeHandle<ATTR_TYPE,FaceContainer>(){}
PerFaceAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,FaceContainer>(ah,n){};
PerFaceAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,FaceContainer>(ah,n){}
};
template <class ATTR_TYPE>
class PerEdgeAttributeHandle: public AttributeHandle<ATTR_TYPE,EdgeContainer>{
public:
PerEdgeAttributeHandle():AttributeHandle<ATTR_TYPE,EdgeContainer>(){}
PerEdgeAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,EdgeContainer>(ah,n){};
PerEdgeAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,EdgeContainer>(ah,n){}
};
template <class ATTR_TYPE>
@ -295,11 +295,13 @@ class TriMesh
n_attr = pva.n_attr;
return (*this);
}
Attribute<ATTR_TYPE> * _handle;
int n_attr;
ATTR_TYPE & operator ()(){ return *((Attribute<ATTR_TYPE> *)_handle)->attribute;}
};
// the camera member (that should keep the intrinsics) is no more needed since 2006, when intrisncs moved into the Shot structure
//Camera<ScalarType> camera; // intrinsic
Shot<ScalarType> shot; // intrinsic && extrinsic
@ -331,13 +333,13 @@ public:
{
typename std::set< PointerToAttribute>::iterator i;
for( i = vert_attr.begin(); i != vert_attr.end(); ++i)
delete ((SimpleTempDataBase<VertContainer>*)(*i)._handle);
delete ((SimpleTempDataBase*)(*i)._handle);
for( i = edge_attr.begin(); i != edge_attr.end(); ++i)
delete ((SimpleTempDataBase<EdgeContainer>*)(*i)._handle);
delete ((SimpleTempDataBase*)(*i)._handle);
for( i = face_attr.begin(); i != face_attr.end(); ++i)
delete ((SimpleTempDataBase<FaceContainer>*)(*i)._handle);
delete ((SimpleTempDataBase*)(*i)._handle);
for( i = mesh_attr.begin(); i != mesh_attr.end(); ++i)
delete ((AttributeBase*)(*i)._handle);
delete ((SimpleTempDataBase*)(*i)._handle);
FaceIterator fi;
for(fi = face.begin(); fi != face.end(); ++fi) (*fi).Dealloc();
@ -349,13 +351,13 @@ public:
size += sizeof(TriMesh)+sizeof(VertexType)*nv+sizeof(FaceType)*nf;
for( i = vert_attr.begin(); i != vert_attr.end(); ++i)
size += ((SimpleTempDataBase<VertContainer>*)(*i)._handle)->SizeOf()*nv;
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*nv;
for( i = edge_attr.begin(); i != edge_attr.end(); ++i)
size += ((SimpleTempDataBase<EdgeContainer>*)(*i)._handle)->SizeOf()*en;
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*en;
for( i = face_attr.begin(); i != face_attr.end(); ++i)
size += ((SimpleTempDataBase<FaceContainer>*)(*i)._handle)->SizeOf()*nf;
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*nf;
for( i = mesh_attr.begin(); i != mesh_attr.end(); ++i)
size += ((AttributeBase*)(*i)._handle)->SizeOf();
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf();
return size;
}

View File

@ -53,7 +53,6 @@ First Working Release (with this comment)
namespace vcg {
template <class STL_CONT>
class SimpleTempDataBase{
public:
virtual ~SimpleTempDataBase() {};
@ -62,8 +61,7 @@ public:
virtual void Reorder(std::vector<size_t> & newVertIndex)=0;
virtual int SizeOf() const = 0;
virtual void * DataBegin() = 0;
//virtual void CopyTo(void * ) = 0;
virtual void * At(unsigned int i ) = 0;
};
template <class TYPE>
@ -110,7 +108,7 @@ private:
};
template <class STL_CONT, class ATTR_TYPE>
class SimpleTempData:public SimpleTempDataBase<STL_CONT>{
class SimpleTempData:public SimpleTempDataBase{
public:
typedef SimpleTempData<STL_CONT,ATTR_TYPE> SimpTempDataType;
@ -138,6 +136,8 @@ class SimpleTempData:public SimpleTempDataBase<STL_CONT>{
ATTR_TYPE & operator[](const typename STL_CONT::iterator & cont){return data[&(*cont)-&*c.begin()];}
ATTR_TYPE & operator[](const int & i){return data[i];}
void * At(unsigned int i ) {return &(*this)[i];};
// update temporary data size
bool UpdateSize(){
if(data.size() != c.size())
@ -161,30 +161,10 @@ class SimpleTempData:public SimpleTempDataBase<STL_CONT>{
int SizeOf() const {return sizeof(ATTR_TYPE);}
void * DataBegin() {return data.empty()?NULL:&(*data.begin());}
//template <typename ATTR_TYPE>
//void CopyTo(void * dest) {
// SimpleTempData<STL_CONT,ATTR_TYPE> * destination = (SimpleTempData<STL_CONT,ATTR_TYPE> *)dest;
// destination->Resize(data.size());
// for(int i = 0; i < data.size(); ++i)
// memcpy((void*)(*destination)[i] , (void*) &( ((char*)( (*this)[i] ))[padding]),sizeof(ATTR_TYPE));
//}
};
class AttributeBase{
public:
virtual ~AttributeBase() {};
AttributeBase() {};
virtual int SizeOf()const = 0;
virtual void * DataBegin() = 0;
};
template <class ATTR_TYPE>
class Attribute: public AttributeBase {
class Attribute: public SimpleTempDataBase {
public:
typedef ATTR_TYPE AttrType;
AttrType * attribute;
@ -192,8 +172,12 @@ Attribute(){attribute = new ATTR_TYPE();}
~Attribute(){delete attribute;}
int SizeOf()const {return sizeof(ATTR_TYPE);}
void * DataBegin(){return attribute;}
void Resize(const int & ) {assert(0);}
void Reorder(std::vector<size_t> & ){assert(0);}
void * At(unsigned int i ) {assert(0);return (void*)0;}
};
}; // end namespace vcg
} // end namespace vcg
#endif