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