1 #ifndef _OCME_COMMIT_
2 #define _OCME_COMMIT_
3 #include "ocme_definition.h"
4 #include "ocme_add.h"
5 #include "boolvector.h"
6 #include "../utils/std_util.h"
7 
8 extern unsigned int lockedMark;
9 
10 
11 
12 // find the removed elements
13 template <class MeshType>
FindRemovedElements(MeshType & m,typename MeshType::template PerVertexAttributeHandle<GISet> & gPosV,typename MeshType::template PerFaceAttributeHandle<GIndex> & gPosF)14 void OCME::FindRemovedElements( MeshType & m,
15                                 typename MeshType::template PerVertexAttributeHandle<GISet> &gPosV,
16                                 typename MeshType::template PerFaceAttributeHandle<GIndex>& gPosF
17                         ){
18 
19                 typename MeshType::FaceIterator fi;
20                 typename MeshType::VertexIterator vi;
21 
22 
23                 std::vector<GIndex> committing_faces;
24                 std::vector<GISet> committing_vertices;
25 
26                 /*
27                         find the GIndex being committed
28                 */
29 
30                 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
31                 {
32                                 GISet gposv = gPosV [*vi];
33                                 if(!gposv.IsUnassigned() )
34                                           committing_vertices.push_back(gposv);
35                 }
36 
37 
38                 for(fi = m.face.begin(); fi != m.face.end(); ++fi ){
39                                                 GIndex gposf = gPosF [*fi];
40                                                 if(!gposf.IsUnassigned() )
41                                                                 committing_faces.push_back(gposf);
42                                 }
43 
44                 /*
45                         find the GIndex that were taken in edit and are not being committed back
46                 */
47 
48                 std::vector<GIndex> deleted_faces;
49                 SetDifference(edited_faces,committing_faces,deleted_faces);
50 sprintf(lgn->Buf(),"del faces %d",deleted_faces.size());
51 lgn->Push();
52                 for(unsigned int i = 0; i < deleted_faces.size(); ++i){
53                                 Cell* c = GetCell(deleted_faces[i].ck,false);
54                                 assert(c);
55                                 c->ecd->deleted_face.SetAsVectorOfMarked();
56                                 c->ecd->deleted_face.SetMarked(deleted_faces[i].i,true);
57                                 toCleanUpCells.push_back(c);
58                                 }
59 
60                 std::vector<GISet> deleted_vertices;
61 
62                 SetDifference(edited_vertices,committing_vertices,deleted_vertices);
63                 for(unsigned int  i = 0; i < deleted_vertices.size(); ++i)
64                         for(GISet::iterator di = deleted_vertices[i].begin(); di != deleted_vertices[i].end();++di )
65                             {
66                                 Cell* c = GetCell((*di).first,false);
67                                 assert(c);
68                                 c->ecd->deleted_vertex.SetAsVectorOfMarked();
69                                 c->ecd->deleted_vertex.SetMarked((*di).second,true);
70                                 toCleanUpCells.push_back(c);
71                                 }
72 
73                 ::RemoveDuplicates(toCleanUpCells);
74 
75 
76 }
77 
78 template <class MeshType>
Commit(MeshType & m,AttributeMapper attr_map)79 void OCME::Commit(MeshType & m, AttributeMapper attr_map){
80 	typedef typename MeshType::ScalarType ScalarType;
81 	typename MeshType::FaceIterator fi;
82 	typename MeshType::VertexIterator vi;
83 
84 
85 	/* first of all take the vcg::attribute storing the GIndex position of the elements in the ocm.
86 		If this operation fails it means you are trying to commit something you did not take
87 		in edit with Edit(). In this case the function return, you should have called AddMesh.
88 	*/
89 
90 		//// create an attibute that will store the address in ocme
91     typename MeshType::template PerVertexAttributeHandle<GISet> gPosVNew =
92               vcg::tri::Allocator<MeshType>::template AddPerVertexAttribute<GISet> (m,"gposNew");
93 
94 
95     typename MeshType::template PerVertexAttributeHandle<GISet> gPosV =
96                 vcg::tri::Allocator<MeshType>::template GetPerVertexAttribute<GISet> (m,"ocme_gindex");
97 	assert(vcg::tri::Allocator<MeshType>::IsValidHandle(m,gPosV));
98 
99 	typename MeshType::template PerFaceAttributeHandle<GIndex> gPosF =
100         vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<GIndex> (m,"ocme_gindex");
101 	assert(vcg::tri::Allocator<MeshType>::IsValidHandle(m,gPosF));
102 
103 	typename MeshType::template PerMeshAttributeHandle<ScaleRange> srE =
104         vcg::tri::Allocator<MeshType>::template GetPerMeshAttribute<ScaleRange> (m,"ocme_range");
105 
106 	assert(vcg::tri::Allocator<MeshType>::IsValidHandle(m,srE));
107 
108 	typename MeshType::template PerVertexAttributeHandle<unsigned char> lockedV =
109         vcg::tri::Allocator<MeshType>::template GetPerVertexAttribute<unsigned char> (m,"ocme_locked");
110 	assert(vcg::tri::Allocator<MeshType>::IsValidHandle(m,lockedV));
111 
112 	typename MeshType::template PerFaceAttributeHandle<unsigned char> lockedF =
113         vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<unsigned char> (m,"ocme_locked");
114 	assert(vcg::tri::Allocator<MeshType>::IsValidHandle(m,lockedF));
115 
116 	typename MeshType::template PerMeshAttributeHandle<std::vector<CellKey> > sel_cells_attr =
117         vcg::tri::Allocator<MeshType>::template GetPerMeshAttribute<std::vector<CellKey> > (m,"sel_cells");
118 	assert(vcg::tri::Allocator<MeshType>::IsValidHandle(m,sel_cells_attr));
119 
120 
121 
122 	for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
123          gPosVNew[vi].Clear();
124 
125     FindRemovedElements(m,gPosV,gPosF);
126 
127 
128 	RecordCellsSetModification();
129 
130 	// find which scale interval will be associated with this mesh
131 	ScaleRange srM = ScaleRangeOfMesh(m);
132 
133 	// find which scale interval has been stored with the mesh at extraction time
134 	ScaleRange sr = srE();
135 
136 	int h;
137         ++generic_bool;                                                 // mark the cells whose attributes are aligned with attr_map
138 
139 
140 	/* Run over all the vertices and move those vertices which are in cells not in the interval sr */
141         Cell * c = NULL; // current cell. Cache the last used cell because very often this is coherent from vertex to vertex
142 
143 
144 
145        // Phase 1: delete the vertices that are marked as deleted in the mesh
146        lgn->Append("deleting vertices marked as D in the mesh");
147      {
148         unsigned int ii = 0;
149          for(vi = m.vert.begin(); vi != m.vert.end(); ++vi,++ii)
150                 if(lockedV[*vi]==0)													//   skip if the vertex is not editable
151         {
152                  GISet   gposv = gPosV[*vi];
153 
154                  if(!gposv.IsUnassigned() && (*vi).IsD()){
155                      for(GISet::iterator dvi = gposv.begin(); dvi != gposv.end(); ++dvi){
156                          Cell * dvc = GetCell((*dvi).first,false);
157                          assert(dvc);
158                          dvc->ecd->deleted_vertex.SetAsVectorOfMarked();
159                          dvc->ecd->deleted_vertex.SetMarked((*dvi).second,true);
160                          toCleanUpCells.push_back(dvc);
161                      }
162                  }
163         }
164      }
165 
166 	/* Here the main cycle. for each face of the mesh put it in the hashed multigrid */
167 	for(fi = m.face.begin(); fi != m.face.end(); ++fi)
168 		if( lockedF[*fi]==0)						// skip if not editable
169 		{
170 			vcg::Box3<ScalarType> facebox;
171 			CellKey ck;
172             GIndex     gposf = gPosF[*fi]; // note: gPosF[] will not be updated because it is won't be used again
173                                                // before it is destroyed
174 
175 		//if( ((&(*fi) - &(*m.face.begin()))%1000) == 0){
176 		//	sprintf(lgn->Buf(),"committed %d faces  \r",&(*fi) - &(*m.face.begin()));
177 		//	lgn->Push();
178 		//}
179 
180 
181 				if((*fi).IsD()){                // face is deleted
182                     if(!gposf.IsUnassigned()){  // it is in the database
183                                                 // remove it from the db
184                         Cell * c = GetCell(gposf.ck,false);
185                         RAssert(c);
186                         c->ecd->deleted_face.SetAsVectorOfMarked();
187                         c->ecd->deleted_face.SetMarked(gposf.i,true);
188                         toCleanUpCells.push_back(c);
189                      }
190                     // it was not in the database. It has been added and remove during editing...forget it
191                     continue;
192                 }
193 
194                 // compute the cell where to put this face
195 				{
196                     // find in which level the face should be
197                     h = ComputeLevel<MeshType>(*fi,srM);
198 
199                     if( sr.Include(h) && !gposf.IsUnassigned()) 		// if	"the level the face should be put" is within the range of the mesh
200                             h = gposf.ck.h;					// then let it be in the same level it was at extraction time
201 
202                     // 2. find the proper cell in the level h
203                     /* very first choice, pick the cell that contains the  min corner of the bounding box */
204                     for(int i = 0; i < 3 ; ++i) facebox.Add((*fi).V(i)->P());
205 
206                     ck = ComputeCellKey(facebox.min,h);
207 
208 //ck = gposf.ck; // DEBUGGING: prevent the face from migrating
209 
210                     if( (!c) || !(c->key == ck))				// check if the current cell is the right one
211                             c = GetCell(ck);				// if not update it
212 			}
213 
214 
215 
216                 if(gposf.IsUnassigned() ){ // it is a brand new face											// this means this face has been added now
217                                 gposf.i  =  c -> AddFace(OFace());			// add the face to it	 and
218                                 gposf.ck =  ck;						// update the GIndex stored in gPosV
219                         }else
220                         if( !(ck == gposf.ck) )	{
221                                 RAssert(c->key==ck);
222                                 toCleanUpCells.push_back(GetCell(gposf.ck,false));		// put gposf.ck in the set of cells that contain removed elements
223                                 MoveFace(gposf,ck); // note: this function updates gposf
224                             }
225 
226 		/* Set the references to the vertices
227 		*/
228                 int vIndex[3];
229                 for(int i = 0; i < 3 ; ++i){
230                         vIndex[i] = gPosV[(*fi).V(i)].Index(ck);
231                         RAssert(c->key == ck);
232                         RAssert(vIndex[i] < (int) c->vert->Size());
233                         // get the index of the vertex in this cell (or -1)
234 						if(vIndex[i]==-1){ // this vertex was not in ck at edit time
235 							 vIndex[i] = gPosVNew[(*fi).V(i)].Index(ck);
236 							 if(vIndex[i]==-1)// not yet added during this commit
237 	                             vIndex[i] = c-> AddVertex(OVertex(*(*fi).V(i)) );			// no: add the vertex to it
238 							 gPosVNew[(*fi).V(i)].Add(GIndex(ck,vIndex[i]));
239                          }
240 
241                          (*c->face)[gposf.i][i] = vIndex[i];
242                          RAssert(vIndex[i] < (int) c->vert->Size());
243                      }
244 
245                 // update the bounding box of the cell c to contain the bbox of the face
246                 c->bbox.Add(facebox,sr);
247 		}
248 
249 		// import all the attributes specified
250 		for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)if( lockedV[*vi]==0){
251 			// for the old copies
252 			for(GISet::CopiesIterator ci = gPosV[*vi].giset.begin();ci != gPosV[*vi].giset.end();++ci){
253 				if( (c==NULL) || !(c->key == (*ci).first)) c = GetCell((*ci).first,false);
254 				RAssert(c);
255 				(*c->vert)[(*ci).second].P() = (*vi).cP();
256 				attr_map.ImportVertex(c,*vi,(*ci).second);
257 			}
258 			// for the new copies
259 			for(GISet::CopiesIterator ci = gPosVNew[*vi].giset.begin();ci != gPosVNew[*vi].giset.end();++ci){
260 				if( (c==NULL) || !(c->key == (*ci).first)) c = GetCell((*ci).first,false);
261 				RAssert(c);
262 				(*c->vert)[(*ci).second].P() = (*vi).cP();
263 				attr_map.ImportVertex(c,*vi,(*ci).second);
264 			}
265 		}
266 
267 		/* update gPosV by removing deleted vertices */
268 			{
269 				for(vi = m.vert.begin(); vi != m.vert.end(); ++vi){
270 					GISet toErase;
271 					for(GISet::CopiesIterator ci = gPosV[*vi].giset.begin(); ci != gPosV[*vi].giset.end();++ci){
272 						Cell * c = GetCell( (*ci).first,false);
273 						assert(c);
274 						c->ecd->deleted_vertex.SetAsVectorOfBool();
275 						if(c->ecd->deleted_vertex.IsMarked((*ci).second))
276 							toErase.Add((*ci));
277 						}
278 						gPosV[*vi].sub(toErase);
279 					}
280 			}
281 
282 			/* now gPosV + gPosVNew is the updated set cells referring the vertex.
283 			   By construction, the intersection of the two is empty
284 			*/
285 
286 
287 			// compare gPosV e gPosVNew to update the borders
288 			for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)if(!(*vi).IsD())
289 			{
290 				unsigned int bi;
291 				GISet fresh_added  = gPosVNew[*vi];
292 
293 				if( fresh_added.giset.size() + gPosV[*vi].giset.size()>1){	// it is a border vertex
294 					if(gPosV[*vi].giset.size() > 1)							// it already was a border vertex
295 						bi  = gPosV[*vi].BI();								// take its global border index
296 					else {
297 						bi = gbi++;											// it is a new border vertex, create a new gbi
298 
299 						/*  if the vertex was only in a cell it means that it was NOT a border,
300 							so  add it to the border of the cell, because it's become a border vertex
301 						*/
302 						if(gPosV[*vi].giset.size() == 1){
303 							GISet::CopiesIterator ci = gPosV[*vi].giset.begin();
304 							Cell * c = GetCell((*ci).first);
305 							RAssert(c);
306 							c->ecd->deleted_vertex.SetAsVectorOfBool();
307 							RAssert(!c->ecd-> deleted_vertex.IsMarked((*ci).second));
308 
309 							if(!BorderExists(c,(*ci).second)){
310 								c->border->AddElem(BorderIndex((*ci).second, bi ));
311 								RAssert((*ci).second<c->vert->Size());
312 							}
313 						}
314 					}
315 
316 					/* add the reference to the border for fresh added cells */
317 					for(GISet::CopiesIterator ci = fresh_added.giset.begin(); ci != fresh_added.giset.end();++ci){
318 						Cell * c = GetCell((*ci).first);
319 						RAssert(c);
320 						c->ecd->deleted_vertex.SetAsVectorOfBool();
321 						RAssert(!c->ecd->deleted_vertex.IsMarked((*ci).second));
322 						RAssert(!BorderExists(c,(*ci).second));
323 						c->border->AddElem(BorderIndex((*ci).second, bi ));
324 						RAssert((*ci).second < c->vert->Size());
325 					}
326 
327 					// add new cell dependencies
328 					GISet total = fresh_added;
329 					total.giset.insert(gPosV[*vi].giset.begin(),gPosV[*vi].giset.end());
330 					for(GISet::CopiesIterator ci = total.giset.begin(); ci != total.giset.end();++ci) {
331 						GISet::CopiesIterator ci1 = ci;++ci1;
332 						for(; ci1 != total.giset.end();++ci1){
333 							Cell * c_in_commit = GetCell((*ci).first,false);
334 							Cell * c1_in_commit = GetCell((*ci1).first,false);
335 							RAssert(c_in_commit);
336 							RAssert(c1_in_commit);
337 							this->CreateDependence(c_in_commit,c1_in_commit);
338 						}
339 					}
340 
341 				}
342 			}
343 		/* mark unreferenced vertices for deletion	in cells included in the selection at edit time 	*/
344 			{
345 				std::vector<bool> todel;
346 				std::vector<bool> border;
347 				for(unsigned int i = 0; i < sel_cells_attr().size(); ++i){
348 					Cell * c = GetCell(sel_cells_attr()[i],false);
349 					RAssert(c);
350 					todel.resize(c->vert->Size(),true);
351 					border.resize(c->vert->Size(),false);
352 					for(unsigned int ii  = 0; ii < c->border->Size(); ++ii)
353 						border[(*c->border)[ii].vi] = true;
354 
355 					for(unsigned int fi = 0; fi < c->face->Size(); ++fi){
356 						for(unsigned int vi  = 0; vi < 3; ++vi)
357 							todel[(*c->face)[fi][vi]] = false;
358 					}
359 					c->ecd->deleted_vertex.SetAsVectorOfMarked();
360 					for(unsigned int ii = 0; ii < c->vert->Size(); ++ii)
361 						if(todel[ii] && border[ii])
362 							c->ecd->deleted_vertex.SetMarked(ii,true);
363 				}
364 			}
365 
366 		lgn->Append("cleaning up");
367         if(!toCleanUpCells.empty()){
368                 RemoveDuplicates		(toCleanUpCells);
369                 RemoveDeletedFaces		(toCleanUpCells);
370                 RemoveDeletedBorder		(toCleanUpCells);
371                 RemoveDeletedVertices	(toCleanUpCells);
372        }
373 
374 		{
375 			for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
376 				if(!(*vi).IsD() && gPosV[*vi].IsUnassigned() && gPosVNew[*vi].IsUnassigned() ){
377 					 CellKey ck = ComputeCellKey((*vi).cP(),srM.max);
378 					 if( (c==NULL) || !(c->key == ck)) {
379 						 c = GetCellC(ck);
380 							if(!c->generic_bool()) {                                            // if it is the first occurrence of the cell
381 								UpdateCellsAttributes(c,attr_map);                              // make sure it contains all the attributes
382 								c->generic_bool = FBool(&generic_bool);
383 								c->generic_bool = true;
384 							}
385 					 }
386 					 int pos = c-> AddVertex(OVertex(*vi) );
387 					 attr_map.ImportVertex(c,*vi,pos);
388 				}
389 
390 		}
391 #ifdef _DEBUG
392 	// DEBUG - check
393 
394 	for(std::vector<Cell*>::iterator ci = toCleanUpCells.begin(); ci != toCleanUpCells.end(); ++ci)
395 		RAssert((*ci)->ecd->deleted_face.Empty());
396 
397 	for(CellsIterator ci = cells.begin(); ci != cells.end(); ++ci)
398 		RAssert((*ci).second->ecd->deleted_face.Empty());
399 
400 #endif
401 	// Phase 7. remove empty cells
402 	/* only a subset of the cells in toCleanUpCells may possibly have become empty */
403 	for(std::vector<Cell*>::iterator ci = toCleanUpCells.begin(); ci != toCleanUpCells.end(); ++ci)
404 		if( (*ci)->IsEmpty()){
405 			sprintf(lgn->Buf(), "remove cell %d %d %d %d\n",(*ci)->key.x,(*ci)->key.y,(*ci)->key.z,(*ci)->key.h);
406 			lgn->Push();
407 			RemoveCell((*ci)->key);
408 		}
409 	toCleanUpCells.clear();
410 
411         vcg::tri::Allocator<MeshType>::template DeletePerVertexAttribute<GISet>(m,gPosVNew);
412         vcg::tri::Allocator<MeshType>::template DeletePerVertexAttribute<GISet>(m,gPosV);
413         vcg::tri::Allocator<MeshType>::template DeletePerVertexAttribute<unsigned char>(m,lockedV);
414 
415         vcg::tri::Allocator<MeshType>::template DeletePerFaceAttribute<GIndex>(m,gPosF);
416         vcg::tri::Allocator<MeshType>::template DeletePerFaceAttribute<unsigned char>(m,lockedF);
417 
418         vcg::tri::Allocator<MeshType>::template DeletePerMeshAttribute<ScaleRange>(m,srE);
419         vcg::tri::Allocator<MeshType>::template DeletePerMeshAttribute<std::vector<CellKey> >(m,sel_cells_attr);
420 
421 
422 
423 	StopRecordCellsSetModification();
424 
425 
426 	this->ClearImpostors(this->touched_cells);		// clear the part of the hierarchy containing the touched cells
427 	this->FillSamples(this->touched_cells);				// touched_cells also contains the new cells
428 	this->BuildImpostorsHierarchyPartial(this->touched_cells);
429 	generic_bool++;
430 	sprintf(lgn->Buf(),"EndCommit"); lgn->Push();
431 }
432 #endif
433