// naja der name sagt es schon tasten abfragen // "normale tasten" GLvoid keyboard ( unsigned char key, int x, int y ) { switch ( key ) { case 27: exit(0); break; case 'a': apoint.z -= 6.2f; break; case 'y': apoint.z += 6.2f; break; case 'o': optimize(*model2, *model); cout << "qual: " << model2->erep/model2->crep << endl; break; case 's': swapEdge(model2->edges[number], *model2, *model); break; case 'c': collapseEdge(model2->edges[number], *model2, *model ); cout << number << endl; break; case 'd': splitEdge(model2->edges[number], *model2, *model ); break; case 'w': roty += 5.5f; break; default: break; } }
void HMesh::removeHeckBertShit(size_t amount) { map<double, pair<int, Edge*> > shortest_edges; for(int i = 0; i < vertices_.size(); i++) { for(Edge* edgy : vertices_[i]->in_edges) { Vertex* v1 = edgy->start; Vertex* v2 = edgy->end; Vertex v_neu = (*v1 + *v2) * 0.5; Vertex v_b1 = v_neu - *v1; Vector3f ev_b1 = Vector3f(v_b1.x, v_b1.y, v_b1.z); double heck_meck = 0; for(int i = 0;i < v1->out_edges.size();i++) { Face* plane = v1->out_edges[i]->face; if(plane != NULL) { Vertex s1 = (*plane->startEdge_->end - *plane->startEdge_->start); Vertex s2 = (*plane->startEdge_->next->end - *plane->startEdge_->start); Vector3f stv1 = Vector3f(s1.x, s1.y, s1.z); Vector3f stv2 = Vector3f(s2.x, s2.y, s2.z); Vector3f normal = stv1.cross(stv2); heck_meck += pow((normal.dot(ev_b1)), 2); } } Vertex v_b2 = v_neu - *v2; Vector3f ev_b2 = Vector3f(v_b2.x, v_b2.y, v_b2.z); for(int i = 0;i < v2->out_edges.size();i++) { Face* plane = v2->out_edges[i]->face; if(plane != NULL) { Vertex s1 = (*plane->startEdge_->end - *plane->startEdge_->start); Vertex s2 = (*plane->startEdge_->next->end - *plane->startEdge_->start); Vector3f stv1 = Vector3f(s1.x, s1.y, s1.z); Vector3f stv2 = Vector3f(s2.x, s2.y, s2.z); Vector3f normal = stv1.cross(stv2); heck_meck += pow((normal.dot(ev_b2)), 2); } } shortest_edges.insert(pair<double, pair<int, Edge*> >(heck_meck, pair<int, Edge*>(i,edgy))); } } collapseEdge(shortest_edges.begin()->second.second); int i = shortest_edges.begin()->second.first; auto elem = find(vertices_[i]->in_edges.begin(), vertices_[i]->in_edges.end(), shortest_edges.begin()->second.second) ; if(elem != vertices_[i]->in_edges.end()) { vertices_[i]->in_edges.erase(elem); } elem = find(vertices_[i]->out_edges.begin(), vertices_[i]->out_edges.end(), shortest_edges.begin()->second.second) ; if(elem != vertices_[i]->out_edges.end()) { vertices_[i]->out_edges.erase(elem); } }
void HMesh::removeShortestShit(size_t amount) { map<double, Edge*> shortest_edges; for(int i = 0; i < vertices_.size(); i++) { for(Edge* edgy : vertices_[i]->out_edges) { if(edgy != NULL) shortest_edges.insert(pair<double, Edge*>((*edgy->end - *edgy->start).length(), edgy)); } } collapseEdge(shortest_edges.begin()->second); for(int i = 0; i < vertices_.size(); i++) { auto elem = find(vertices_[i]->out_edges.begin(), vertices_[i]->out_edges.end(), shortest_edges.begin()->second) ; if(elem != vertices_[i]->out_edges.end()) { vertices_[i]->out_edges.erase(elem); } } }
void HMesh::removeMelaxShit(size_t amount) { map<double, pair<int, Edge*> > shortest_edges; for(int i = 0; i < vertices_.size(); i++) { for(Edge* edgy : vertices_[i]->in_edges) { Vertex* u = edgy->start; Vertex* v = edgy->end; double uv_length = (*v - *u).length(); vector<Vector3f> uv_planes; vector<Vector3f> u_planes; for(int i = 0;i < u->out_edges.size();i++) { Face* plane = u->out_edges[i]->face; if(plane != NULL) { Vertex s1 = (*plane->startEdge_->end - *plane->startEdge_->start); Vertex s2 = (*plane->startEdge_->next->end - *plane->startEdge_->start); Vector3f stv1 = Vector3f(s1.x, s1.y, s1.z); Vector3f stv2 = Vector3f(s2.x, s2.y, s2.z); Vector3f normal = stv1.cross(stv2); uv_planes.push_back(normal); u_planes.push_back(normal); } } for(int i = 0;i < v->out_edges.size();i++) { Face* plane = v->out_edges[i]->face; if(plane != NULL) { Vertex s1 = (*plane->startEdge_->end - *plane->startEdge_->start); Vertex s2 = (*plane->startEdge_->next->end - *plane->startEdge_->start); Vector3f stv1 = Vector3f(s1.x, s1.y, s1.z); Vector3f stv2 = Vector3f(s2.x, s2.y, s2.z); Vector3f normal = stv1.cross(stv2); uv_planes.push_back(normal); } } double max_val = 0; for(int j = 0; j < u_planes.size(); j++) { Vector3f normal_a = u_planes[j]; double min_val = 1000000; for(int k = 0; k < uv_planes.size(); k++) { double step = (1 - (normal_a.dot(uv_planes[k]))); if(step < min_val) min_val = step; } if(min_val > max_val) max_val = min_val; } double mex_meck = uv_length * max_val; shortest_edges.insert(pair<double, pair<int, Edge*> >(mex_meck, pair<int, Edge*>(i,edgy))); } } collapseEdge(shortest_edges.begin()->second.second); int i = shortest_edges.begin()->second.first; auto elem = find(vertices_[i]->in_edges.begin(), vertices_[i]->in_edges.end(), shortest_edges.begin()->second.second) ; if(elem != vertices_[i]->in_edges.end()) { vertices_[i]->in_edges.erase(elem); } elem = find(vertices_[i]->out_edges.begin(), vertices_[i]->out_edges.end(), shortest_edges.begin()->second.second) ; if(elem != vertices_[i]->out_edges.end()) { vertices_[i]->out_edges.erase(elem); } }
bool DecimationMesh::decimate() { EdgeCollapse * collapse = static_cast<EdgeCollapse *>(mHeap.pop()); if (collapse == NULL) return false; // Stop the collapse when we only have two triangles left // (the smallest entity representable) if (mFaces.size() - mNumCollapsedFaces == 2) return false; unsigned int e1 = collapse->halfEdge; unsigned int e2 = mEdges[e1].pair; unsigned int v1 = mEdges[e1].vert; unsigned int v2 = mEdges[e2].vert; unsigned int v3 = mEdges[mEdges[e1].prev].vert; unsigned int v4 = mEdges[mEdges[e2].prev].vert; unsigned int f1 = mEdges[e1].face; unsigned int f2 = mEdges[e2].face; std::cout << "Collapsing faces " << f1 << " and " << f2 << std::endl; std::cout << "Collapsing edges " << e1 << ", " << mEdges[e1].next << ", " << mEdges[e1].prev; std::cout << ", " << e2 << ", " << mEdges[e2].next << " and " << mEdges[e2].prev << std::endl; std::cout << "Collapsing vertex " << v1 << std::endl; // Verify that the collapse is valid, exit if not so if (!isValidCollapse(collapse)) { delete collapse; mHalfEdge2EdgeCollapse[e1] = NULL; mHalfEdge2EdgeCollapse[e2] = NULL; std::cout << "failed..." << std::endl; return false; } // We want to remove v1, so we need to connect all of v1's half-edges to v2 unsigned int edge = mVerts[v1].edge; do { mEdges[edge].vert = v2; edge = mEdges[mEdges[edge].pair].next; } while (edge != mVerts[v1].edge); // Make sure v2 points to a valid edge while (mEdges[mVerts[v2].edge].face == f1 || mEdges[mVerts[v2].edge].face == f2) mVerts[v2].edge = mEdges[mEdges[ mVerts[v2].edge ].pair].next; // Make sure v3 points to a valid edge while (mEdges[mVerts[v3].edge].face == f1) mVerts[v3].edge = mEdges[mEdges[ mVerts[v3].edge ].pair].next; // Make sure v4 points to a valid edge while (mEdges[mVerts[v4].edge].face == f2) mVerts[v4].edge = mEdges[mEdges[ mVerts[v4].edge ].pair].next; // Redirect pair pointers mEdges[mEdges[mEdges[e1].next].pair].pair = mEdges[mEdges[e1].prev].pair; mEdges[mEdges[mEdges[e1].prev].pair].pair = mEdges[mEdges[e1].next].pair; mEdges[mEdges[mEdges[e2].next].pair].pair = mEdges[mEdges[e2].prev].pair; mEdges[mEdges[mEdges[e2].prev].pair].pair = mEdges[mEdges[e2].next].pair; // Move v2 to its new position mVerts[v2].pos = collapse->position; // One edge collapse further removes 2 additional collapse // candidates from the heap if (mHalfEdge2EdgeCollapse[mEdges[e1].prev] != NULL) delete mHeap.remove(mHalfEdge2EdgeCollapse[mEdges[e1].prev]); mHalfEdge2EdgeCollapse[mEdges[mEdges[e1].prev].pair] = mHalfEdge2EdgeCollapse[mEdges[e1].next]; if (mHalfEdge2EdgeCollapse[mEdges[e2].next] != NULL) delete mHeap.remove(mHalfEdge2EdgeCollapse[mEdges[e2].next]); mHalfEdge2EdgeCollapse[mEdges[mEdges[e2].next].pair] = mHalfEdge2EdgeCollapse[mEdges[e2].prev]; // Make sure the edge collapses point to valid edges if (mHalfEdge2EdgeCollapse[mEdges[e1].next] != NULL) mHalfEdge2EdgeCollapse[mEdges[e1].next]->halfEdge = mEdges[mEdges[e1].prev].pair; if (mHalfEdge2EdgeCollapse[mEdges[e2].prev] != NULL) mHalfEdge2EdgeCollapse[mEdges[e2].prev]->halfEdge = mEdges[mEdges[e2].next].pair; delete collapse; // Collapse the neighborhood collapseFace(f1); collapseFace(f2); collapseEdge(e1); collapseEdge(mEdges[e1].next); collapseEdge(mEdges[e1].prev); collapseEdge(e2); collapseEdge(mEdges[e2].next); collapseEdge(mEdges[e2].prev); collapseVertex(v1); // Finally, loop through neighborhood of v2 and update all edge collapses // (and remove possible invalid cases) updateVertexProperties(v2); edge = mVerts[v2].edge; do { unsigned int face = mEdges[edge].face; unsigned int vert = mEdges[mEdges[edge].pair].vert; if (!isFaceCollapsed(face)) updateFaceProperties(face); if (!isVertexCollapsed(vert)) updateVertexProperties(vert); collapse = mHalfEdge2EdgeCollapse[edge]; if (collapse != NULL) { if (!isValidCollapse(collapse)) { delete mHeap.remove(collapse); mHalfEdge2EdgeCollapse[edge] = NULL; mHalfEdge2EdgeCollapse[mEdges[edge].pair] = NULL; std::cout << "Removed one invalid edge collapse" << std::endl; } else { computeCollapse(collapse); mHeap.update(collapse); } } edge = mEdges[mEdges[edge].pair].next; } while (edge != mVerts[v2].edge); //mHeap.print(std::cout); return true; }
uint32_t ApexQuadricSimplifier::simplify(uint32_t subdivision, int32_t maxSteps, float maxError, IProgressListener* progressListener) { float maxLength = 0.0f; uint32_t nbCollapsed = 0; if (subdivision > 0) { maxLength = (mBounds.minimum - mBounds.maximum).magnitude() / subdivision; } uint32_t progressCounter = 0; uint32_t maximum = maxSteps >= 0 ? maxSteps : mHeap.size(); HierarchicalProgressListener progress(100, progressListener); progress.setSubtaskWork(90, "Isomesh simplicifaction"); #if TESTING testHeap(); #endif while (maxSteps == -1 || (maxSteps-- > 0)) { if ((++progressCounter & 0xff) == 0) { const int32_t percent = (int32_t)(100 * progressCounter / maximum); progress.setProgress(percent); } bool edgeFound = false; QuadricEdge* e = NULL; while (mHeap.size() - mNumDeletedHeapElements > 1) { e = mHeap[1]; if (maxError >= 0 && e->cost > maxError) { // get me out of here edgeFound = false; break; } if (legalCollapse(*e, maxLength)) { heapRemove(1, false); #if TESTING testHeap(); #endif edgeFound = true; break; } uint32_t vNr0 = e->vertexNr[0]; uint32_t vNr1 = e->vertexNr[1]; QuadricVertex* qv0 = mVertices[vNr0]; QuadricVertex* qv1 = mVertices[vNr1]; heapRemove(1, qv0->bDeleted == 0 && qv1->bDeleted == 0); #if TESTING testHeap(); #endif } if (!edgeFound) { break; } collapseEdge(*e); nbCollapsed++; } progress.completeSubtask(); progress.setSubtaskWork(10, "Heap rebuilding"); progressCounter = mNumDeletedHeapElements; while (mNumDeletedHeapElements > 0) { if ((mNumDeletedHeapElements & 0x7f) == 0) { const int32_t percent = (int32_t)(100 * (progressCounter - mNumDeletedHeapElements) / progressCounter); progress.setProgress(percent); } #if TESTING testHeap(); #endif mNumDeletedHeapElements--; heapUpdate(mHeap.size() - 1 - mNumDeletedHeapElements); } progress.completeSubtask(); #if TESTING testHeap(); #endif return nbCollapsed; }
bool NTriangulation::simplifyToLocalMinimum(bool perform) { BoundaryComponentIterator bit; unsigned long nTriangles; unsigned long iTriangle; // unsigned long nEdges; // unsigned long iEdge; // std::deque<NEdgeEmbedding>::const_iterator embit, embbeginit, embendit; bool changed = false; // Has anything changed ever (for return value)? bool changedNow = true; // Did we just change something (for loop control)? { // Begin scope for change event span. ChangeEventSpan span(this); while (changedNow) { changedNow = false; ensureSkeleton(); // Crush edges if we can. if (countVertices() > components().size() && countVertices() > boundaryComponents_.size()) { for (NEdge* edge : edges()) if (collapseEdge(edge, true, perform)) { changedNow = changed = true; break; } if (changedNow) { if (perform) continue; else return true; } } // Look for internal simplifications. for (NEdge* edge : edges()) { if (threeTwoMove(edge, true, perform)) { changedNow = changed = true; break; } if (twoZeroMove(edge, true, perform)) { changedNow = changed = true; break; } if (twoOneMove(edge, 0, true, perform)) { changedNow = changed = true; break; } if (twoOneMove(edge, 1, true, perform)) { changedNow = changed = true; break; } } if (changedNow) { if (perform) continue; else return true; } for (NVertex* vertex : vertices()) if (twoZeroMove(vertex, true, perform)) { changedNow = changed = true; break; } if (changedNow) { if (perform) continue; else return true; } // Look for boundary simplifications. if (hasBoundaryTriangles()) { for (bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) { // Run through triangles of this boundary component looking // for shell boundary moves. nTriangles = (*bit)->countTriangles(); for (iTriangle = 0; iTriangle < nTriangles; iTriangle++) { if (shellBoundary((*bit)->triangle(iTriangle)-> front().tetrahedron(), true, perform)) { changedNow = changed = true; break; } } if (changedNow) break; } if (changedNow) { if (perform) continue; else return true; } } } } // End scope for change event span. return changed; }
void AutoTriangleMesh<PointType>::ensureEdgeLength(const typename AutoTriangleMesh<PointType>::BasePoint& center,double radius,double minEdgeLength) { double radius2=radius*radius; /* Iterate through all triangles: */ FaceIterator faceIt=BaseMesh::beginFaces(); while(faceIt!=BaseMesh::endFaces()) { /* Check quickly (ha!) if face overlaps area of influence: */ bool overlaps=false; Edge* e=faceIt->getEdge(); do { if(sqrDist(*e->getStart(),center)<=radius2) { overlaps=true; break; } /* Go to next edge: */ e=e->getFaceSucc(); } while(e!=faceIt->getEdge()); if(overlaps) { /* Calculate face's minimum edge length: */ Edge* shortestEdge=0; double shortestEdgeLength2=minEdgeLength*minEdgeLength; Edge* e=faceIt->getEdge(); do { /* Calculate edge's squared length: */ #if 1 double edgeLength2=sqrDist(*e->getStart(),*e->getEnd()); #else /* Calculate normal vectors for edge's vertices: */ float normal1[3],normal2[3]; calcNormal(e->getStart(),normal1); calcNormal(e->getEnd(),normal2); float dist1=0.0f; float dist2=0.0f; float edgeLength2=0.0f; float normal1Length2=0.0f; float normal2Length2=0.0f; for(int i=0;i<3;++i) { float dist=(*e->getEnd())[i]-(*e->getStart())[i]; normal1Length2+=normal1[i]*normal1[i]; normal2Length2+=normal2[i]*normal2[i]; dist1+=dist*normal1[i]; dist2+=dist*normal2[i]; edgeLength2+=dist*dist; } dist1=fabsf(dist1)/sqrtf(normal1Length2); dist2=fabsf(dist2)/sqrtf(normal2Length2); float edgeLength=sqrtf(edgeLength2)+5.0f*(dist1+dist2); edgeLength2=edgeLength*edgeLength; #endif if(shortestEdgeLength2>edgeLength2&&canCollapseEdge(e)) { shortestEdge=e; shortestEdgeLength2=edgeLength2; } /* Go to next edge: */ e=e->getFaceSucc(); } while(e!=faceIt->getEdge()); /* Go to next triangle: */ ++faceIt; /* Check whether the shortest collapsible triangle edge is too short: */ if(shortestEdge!=0) { /* Skip next face if it will be removed by edge collapse: */ if(faceIt==shortestEdge->getOpposite()->getFace()) ++faceIt; /* Collapse shortest collapsible edge: */ collapseEdge(shortestEdge); } } else { /* Go to the next triangle: */ ++faceIt; } } }