Пример #1
0
Mesh *Mesh::parallelSubdivide(TaskQueue *tq, int branch){
	int n = numFaces();
	int b = branch;
	cout<< " building winged edges " << endl;
	EdgeMap *em = new EdgeMap(numVertices()); 
	em->putAll(faces); 
	cout << " forking " << endl;    
	while (n / b < 5 && b > 1){
		b /= 2;
	}
	if (branch != b){
		cerr<<"Warning: branch factor reduced from " << branch << " to " << b << endl;
	} 
	int range = n / b + 1; 
	//SubdivideTask tasks[b];
	SubdivideTask *tasks = new SubdivideTask[b];
	for (int i = 0; i < b; i++){
		int min = i * range; 
		if (min >= n) {b=i; break;} 
		int max = ((i + 1) *range);
		if (max > n) max = n;  
		
		tasks[i] = SubdivideTask(this, em, min, max); 
		tq->enqueue(&tasks[i]);
	} 

	for (int i = 0; i < b; i++){
		tasks[i].join(); 
	}
	cout << "merging" << endl;
	Mesh* val = merge(tasks, b);
	delete em;
	delete[] tasks;
	return val;   
}
// Calculates per edge the neighbour data (= edgeCells)
void Foam::FECCellToFaceStencil::calcEdgeBoundaryData
(
    const boolList& isValidBFace,
    const labelList& boundaryEdges,
    EdgeMap<labelList>& neiGlobal
) const
{
    neiGlobal.resize(2*boundaryEdges.size());

    labelHashSet edgeGlobals;

    forAll(boundaryEdges, i)
    {
        label edgeI = boundaryEdges[i];

        neiGlobal.insert
        (
            mesh().edges()[edgeI],
            calcFaceCells
            (
                isValidBFace,
                mesh().edgeFaces(edgeI),
                edgeGlobals
            )
        );
    }
Пример #3
0
void makeEdgeMap(int num_tris, const int3 tri_ndxs[],
                 int num_verts, const float3 v[])
{
    for (int i=0; i<num_tris; i++) {
        for (int j=0; j<3; j++) {
            Edge e(v[tri_ndxs[i][j]], v[tri_ndxs[i][(j+1)%3]]);
            EdgeMap::iterator e_iter = edge_map.find(e);
            if (e_iter != edge_map.end()) {
                e_iter->second.push_back(i);
            } else {
                FaceList face_list(1,i);
                edge_map[e] = face_list;
            }
        }
    }

    for (int i=0; i<num_tris; i++) {
        printf("tri: %d\n", i);
        for (int j=0; j<3; j++) {
            printf("  edg: %d\n", j);
            pair<int,int> ndx(tri_ndxs[i][j], tri_ndxs[i][(j+1)%3]);
            if (ndx.first > ndx.second) {
                std::swap(ndx.first, ndx.second);
            }
            Edge e(v[ndx.first], v[ndx.second]);
            FaceList face_list = edge_map[e];
            for (FaceList::iterator iter = face_list.begin(); iter != face_list.end(); iter++) {
                int face = *iter;
                if (face != i) {
                    printf("    other %d\n", face);
                    bool found_match = false;
                    for (int z=0; z<3; z++) {
                        pair<int,int> ndx2(tri_ndxs[face][z], tri_ndxs[face][(z+1)%3]);
                        if (ndx2.first > ndx2.second) {
                            std::swap(ndx2.first, ndx2.second);
                        }

                        if (ndx == ndx2) {
                            printf("match\n");
                            found_match = true;
                            break;
                        }
                    }
                    if (!found_match) {
                        int3 ndxs = tri_ndxs[face];
                        for (int z=0; z<3; z++) {
                            if (all(e.v0 == v[ndxs[z]])) {
                                printf("        ndx=%d\n", z);
                            } else if (all(e.v1 == v[ndxs[z]])) {
                                printf("        ndx=%d\n", z);
                            }
                        }
                    }
                }
            }
        }
    }
}
Пример #4
0
 /**
 * Return first path found from start vertex to end vertex
 * as a vector of edges, or NULL of no such path is found.
 */
 bool findDfsVertexPath(vector<Vertex*> &path, Vertex *start, const Vertex *end) const
 {
     path.clear();
     if (mEdges.find(start) != mEdges.end()) {
         path.push_back(start);
         return findDfsVertexPathRec(path, end);
     }
     return false;
 }
Пример #5
0
 /**
 * Return first path found from start vertex to end vertex
 * as a vector of edges, or NULL of no such path is found.
 */
 bool findDfsVertexPathMarking(vector<Vertex*> &path, Vertex *start, const Vertex *end)
 {
     mMarks.clear();
     path.clear();
     if (mEdges.find(start) != mEdges.end()) {
         mMarks.insert(start);
         path.push_back(start);
         return findDfsVertexPathMarkingRec(path, end);
     }
     return false;
 }
Пример #6
0
/**
 * Gets all adjacent vertices to the parameter vertex.
 * @param v - the vertex to get neighbors from
 * @return a vector of vertices
 */
vector<Vertex> Graph::getAdjacent(Vertex v) const
{
    assertExists(v, "getAdjacent");

    vector<Vertex> ret;
    EdgeMap edges = graph.at(v);
    EdgeMap::iterator it;
    for (it = edges.begin(); it != edges.end(); ++it)
        ret.push_back(it->second.dest);

    return ret;
}
Пример #7
0
 /**
 *  Add an edge if both vertices are non-NULL and distinct
 */
 bool addEdge(Vertex *vertA, Vertex *vertB) 
 {
     if (vertA == NULL || vertB == NULL || vertA == vertB)
         return false;                   // no side effects on failure
     addVertex(vertA);
     addVertex(vertB);
     if (mEdges.find(vertA) == mEdges.end()) {
         mEdges.insert(EdgeMap::value_type(vertA, new VertSet()));
     }
     VertSet *nexts = mEdges.at(vertA);
     return   nexts->insert(vertB).second;
 }
Пример #8
0
void edgemapwork(void){
    EdgeMap::const_iterator iter;
    //set up halfedge sym pointer
    for(iter = edgemap.begin(); iter != edgemap.end(); iter++){
	EdgeMap::const_iterator iter1;
	EdgeMap::const_iterator iter2;
	Pair p1(iter->first.a,iter->first.b);
	Pair p2(iter->first.b,iter->first.a);
	iter1 = edgemap.find(p1);
	iter2 = edgemap.find(p2);
	iter2->second->sym = iter1->second;
    }	
}
Пример #9
0
 /**
  * Find best predecessor found so far to the specified node
  *
  * @param n Node as destination to find best predecessor for
  *
  * @return Predecessor node
  */
 gcc_pure
 Node GetPredecessor(const Node node) const {
   // Try to find the given node in the node_parent_map
   edge_const_iterator it = edges.find(node);
   if (it == edges.end())
     // first entry
     // If the node wasn't found
     // -> Return the given node itself
     return node;
   else
     // If the node was found
     // -> Return the parent node
     return it->second.parent;
 }
Пример #10
0
void triangularizationte(){
    int newfacesnum = 0;	//number of faces @ the end
    Face newface;
    vector<Face> newFaces;
    int index = 0;
    HalfEdge mynewhalfedge[3];

    for(int i = 0 ; i < numfaces ; ++i){
	if(3 == faxes[i].numedges){
	    ++newfacesnum;
	} else{
	    newfacesnum += faxes[i].numedges - 2;}
    }

    for(int i = 0; i < newfacesnum; i++)
	newFaces.push_back(newface);

    for(int i = 0 ; i< numfaces; i++){
	if(3 == faxes[i].numedges){
	    //triangle
	    newFaces[index].numedges = 3;
	    newFaces[index].ver = new Vertex[3];
	    for(int k=0 ; k < 3; k++){
		newFaces[index].ver[k] = faxes[i].ver[k];
		newFaces[index].ver[k].id = faxes[i].ver[k].id;
	    }
	    ++index;
	} else {
	    //polygon to be split into triangles
	    for(int j = 0 ; j< faxes[i].numedges-2; j++){
		newFaces[index+j].numedges = 3;
		newFaces[index+j].ver = new Vertex[3];
		for(int k=0 ; k<3; k++){
		    if( k==0 ){
			newFaces[index+j].ver[k] = faxes[i].ver[0];
			newFaces[index+j].ver[k].id = faxes[i].ver[0].id;
		    } else{
			newFaces[index+j].ver[k] = faxes[i].ver[k+j];
			newFaces[index+j].ver[k].id = faxes[i].ver[k+j].id;
		    }
		}
	    }
	    index += faxes[i].numedges - 2;
	}
    }
 
    for(int i = 0; i < newfacesnum; ++i){
	newFaces[i].listEdge = &mynewhalfedge[0];
	for(int j = 0 ; j < 3; ++j){
	    mynewhalfedge[j].head = &newFaces[i].ver[(j+1) % 3];
	    mynewhalfedge[j].thisface = &newFaces[i];
	    mynewhalfedge[j].next = &mynewhalfedge[(j+1) % 3];
	    Pair pair(newFaces[i].ver[j].id, newFaces[i].ver[(j+1) % 3].id);			
	    edgemap.insert(EdgeMap::value_type(pair, &mynewhalfedge[j]));						
	}
    }
    edgemapwork();
    numfaces = newfacesnum;
    faxes = newFaces;
}
Пример #11
0
    void * getDirectedEdge(Vector3 const & e0, Vector3 const & e1) const
    {
      typedef std::pair<EdgeMap::const_iterator, EdgeMap::const_iterator> IteratorRange;
      Long3Pair base_key(toGrid(e0), toGrid(e1));

      // Every edge within welding distance of the given edge must be inside a neighbor of the grid cell containing the edge
      for (int dx0 = -1; dx0 <= 1; ++dx0)
        for (int dy0 = -1; dy0 <= 1; ++dy0)
          for (int dz0 = -1; dz0 <= 1; ++dz0)
            for (int dx1 = -1; dx1 <= 1; ++dx1)
              for (int dy1 = -1; dy1 <= 1; ++dy1)
                for (int dz1 = -1; dz1 <= 1; ++dz1)
                {
                  Long3Pair key(Long3(base_key.first.x + dx0, base_key.first.y + dy0, base_key.first.z + dz0),
                                Long3(base_key.second.x + dx1, base_key.second.y + dy1, base_key.second.z + dz1));
                  IteratorRange nbrs = edge_map.equal_range(key);
                  for (EdgeMap::const_iterator ni = nbrs.first; ni != nbrs.second; ++ni)
                  {
                    if ((ni->second.e0 - e0).squaredLength() <= squared_weld_radius
                     && (ni->second.e1 - e1).squaredLength() <= squared_weld_radius)
                      return ni->second.edge;
                  }
                }

      return NULL;
    }
Пример #12
0
    EdgeMap compute_edge_map(const MatrixIr& faces) {
        assert(faces.cols() == 3);
        EdgeMap result;
        const size_t num_faces = faces.rows();
        for (size_t i=0; i<num_faces; i++) {
            const Vector3I& f = faces.row(i);
            Triplet e0(f[1], f[2]);
            Triplet e1(f[2], f[0]);
            Triplet e2(f[0], f[1]);

            result.insert(e0, i);
            result.insert(e1, i);
            result.insert(e2, i);
        }

        return result;
    }
Пример #13
0
  /** 
   * Clears the queues
   */
  void Clear() {
    // Clear the search queue
    q.clear();

    // Clear EdgeMap
    edges.clear();

    current_value = 0;
  }
Пример #14
0
void PolyMesh::buildEdges( Face* f, osg::Vec3Array* refArray, EdgeMap& emap )
{
    osg::Vec3 p1, p2;
    unsigned int size = f->_pts.size();
    for ( unsigned int i=0; i<size; ++i )
    {
        unsigned int i1=(*f)(i%size), i2=(*f)((i+1)%size);
        if ( i1<refArray->size() ) p1 = (*refArray)[i1];
        else p1 = (*f)[i%size];
        if ( i2<refArray->size() ) p2 = (*refArray)[i2];
        else p2 = (*f)[(i+1)%size];

        PolyMesh::Segment p = getSegment( p1, p2 );
        if ( emap.find(p)==emap.end() )
            emap[p] = new PolyMesh::Edge( p.first, p.second );
        emap[p]->hasFace( f, true );
    }
}
Пример #15
0
//------------------------------------------------------------------------------
// generate display IDs for Hbr edges
static void
createEdgeNumbers(std::vector<Hface const *> faces) {

    typedef std::map<Hhalfedge const *, int> EdgeMap;
    EdgeMap edgeMap;

    typedef std::vector<Hhalfedge const *>   EdgeVec;
    EdgeVec edgeVec;

    { // map half-edges into unique edge id's

        for (int i=0; i<(int)faces.size(); ++i) {
            Hface const * f = faces[i];
            for (int j=0; j<f->GetNumVertices(); ++j) {
                Hhalfedge const * e = f->GetEdge(j);
                if (e->IsBoundary() or (e->GetRightFace()->GetID()>f->GetID())) {
                    int id = (int)edgeMap.size();
                    edgeMap[e] = id;
                }
            }
        }
        edgeVec.resize(edgeMap.size());
        for (EdgeMap::const_iterator it=edgeMap.begin(); it!=edgeMap.end(); ++it) {
            edgeVec[it->second] = it->first;
        }
    }

    static char buf[16];
    for (int i=0; i<(int)edgeVec.size(); ++i) {

        Hhalfedge const * e = edgeVec[i];

        float sharpness = e->GetSharpness();
        if (sharpness>0.0f) {

            Vertex center(0.0f, 0.0f, 0.0f);
            center.AddWithWeight(e->GetOrgVertex()->GetData(), 0.5f);
            center.AddWithWeight(e->GetDestVertex()->GetData(), 0.5f);

            snprintf(buf, 16, "%g", sharpness);
            g_font->Print3D(center.GetPos(), buf, std::min(8,(int)sharpness+4));
        }
    }
}
Пример #16
0
void Foam::syncTools::combine
(
    EdgeMap<T>& edgeValues,
    const CombineOp& cop,
    const edge& index,
    const T& val
)
{
    typename EdgeMap<T>::iterator iter = edgeValues.find(index);

    if (iter != edgeValues.end())
    {
        cop(iter(), val);
    }
    else
    {
        edgeValues.insert(index, val);
    }
}
Пример #17
0
/**
 * Inserts an edge between two vertices.
 * A boolean is returned for use with the random graph generation.
 * Hence, an error is not thrown when it fails to insert an edge.
 * @param u - one vertex the edge is connected to
 * @param v - the other vertex the edge is connected to
 * @return whether inserting the edge was successful
 */
bool Graph::insertEdge(Vertex u, Vertex v)
{
    assertExists(u, __func__);
    assertExists(v, __func__);

    EdgeMap uEdges = graph[u];

    // "fail" silently for random graph generation
    if (uEdges.find(v) != uEdges.end())
        return false;

    Edge uEdge(u, v, -1, "");
    graph[u].insert(make_pair(v, uEdge));

    Edge vEdge(v, u, -1, "");
    graph[v].insert(make_pair(u, vEdge));

    return true;
}
Пример #18
0
    bool findDfsVertexPathRec(vector<Vertex*> &path, const Vertex *end) const
    {
        Vertex *lastVert = path.back();
        if (lastVert == end)
            return  true;

        if (mEdges.find(lastVert) != mEdges.end()) {
            VertSet *nexts = mEdges.at(lastVert);
            for (auto it = nexts->begin(); it != nexts->end(); ++it) {                
                path.push_back(*it);
                bool found = findDfsVertexPathRec(path, end);
                if ( found )
                    return found;
                else
                    path.pop_back();
            }
        }
        return false;
    }
Пример #19
0
  /** 
   * Clears the queues
   */
  void Clear() {
    // Clear the search queue
    while (!q.empty())
      q.pop();

    // Clear EdgeMap
    edges.clear();

    current_value = 0;
  }
Пример #20
0
int findEdgeVertical(int x, int y_start, int y_end, const rgbd::View view, EdgeMap& edge_map)
{
    if (y_end - y_start < min_segment_size)
        return -1;

    geo::Vector3 p1_3d, p2_3d;
    if (!view.getPoint3D(x, y_start, p1_3d) || !view.getPoint3D(x, y_end, p2_3d))
        return -1;

    geo::Vec2 p1(p1_3d.y, -p1_3d.z);
    geo::Vec2 p2(p2_3d.y, -p2_3d.z);
    geo::Vec2 n = (p2 - p1).normalized();

    int y_edge = -1;
    float max_dist_sq = 0;
    for(int y2 = y_start; y2 <= y_end; ++y2)
    {
        geo::Vector3 p_3d;
        if (!view.getPoint3D(x, y2, p_3d))
            continue;

        geo::Vec2 p(p_3d.y, -p_3d.z);

        // Calculate distance of p to line (p1, p2)
        geo::Vec2 p1_p = p - p1;

        float dist_sq = (p1_p - (p1_p.dot(n) * n)).length2();

        if (dist_sq > max_dist_sq)
        {
            max_dist_sq = dist_sq;
            y_edge = y2;
        }
    }

    if (y_edge < 0)
        return -1;

    float d = view.getDepth(x, y_edge);
    if (d > max_range)
        return -1;

    float th = d * bla;
    if (max_dist_sq < (th * th))
        return -1;

    // Add edge point
    edge_map.addEdgePoint(x, y_edge, 0, 1);

    // Recursively find edges
    findEdgeVertical(x, y_start, y_edge, view, edge_map);

    return y_edge;
}
Пример #21
0
  /**
   * Add node to search queue
   *
   * @param n Destination node to add
   * @param pn Previous node
   * @param e Edge distance (previous to this)
   * @return false if this link was worse than an existing one
   */
  bool Push(const Node node, const Node parent, unsigned edge_value = 0) {
    // Try to find the given node n in the EdgeMap
    edge_iterator it = edges.find(node);
    if (it == edges.end())
      // first entry
      // If the node wasn't found
      // -> Insert a new node
      it = edges.insert(std::make_pair(node, Edge(parent, edge_value))).first;
    else if (it->second.value > edge_value)
      // If the node was found and the new value is smaller
      // -> Replace the value with the new one
      it->second = Edge(parent, edge_value);
    else
      // If the node was found but the new value is higher or equal
      // -> Don't use this new leg
      return false;

    q.push(Value(edge_value, it));
    return true;
  }
Пример #22
0
int findEdgeHorizontal(int y, int x_start, int x_end, const rgbd::View view, EdgeMap& edge_map)
{
    if (x_end - x_start < min_segment_size)
        return -1;

    geo::Vector3 p1_3d, p2_3d;
    if (!view.getPoint3D(x_start, y, p1_3d) || !view.getPoint3D(x_end, y, p2_3d))
        return -1;

    geo::Vec2 p1(p1_3d.x, -p1_3d.z);
    geo::Vec2 p2(p2_3d.x, -p2_3d.z);
    geo::Vec2 n = (p2 - p1).normalized();

    int x_edge = -1;
    float max_dist_sq = 0;
    for(int x2 = x_start; x2 <= x_end; ++x2)
    {
        geo::Vector3 p_3d;
        if (!view.getPoint3D(x2, y, p_3d))
            continue;

        geo::Vec2 p(p_3d.x, -p_3d.z);

        // Calculate distance of p to line (p1, p2)
        geo::Vec2 p1_p = p - p1;

        float dist_sq = (p1_p - (p1_p.dot(n) * n)).length2();

        if (dist_sq > max_dist_sq)
        {
            max_dist_sq = dist_sq;
            x_edge = x2;
        }
    }

    if (x_edge < 0)
        return -1;

    float d = view.getDepth(x_edge, y);
    if (d > max_range)
        return -1;

    float th = d * bla;
    if (max_dist_sq < (th * th))
        return -1;

    // Add edge point
    edge_map.addEdgePoint(x_edge, y, 1, 0);

    // Recursively find edges
    findEdgeHorizontal(y, x_start, x_edge, view, edge_map);

    return x_edge;
}
Пример #23
0
bool Foam::triSurfaceMesh::addFaceToEdge
(
    const edge& e,
    EdgeMap<label>& facesPerEdge
)
{
    EdgeMap<label>::iterator eFnd = facesPerEdge.find(e);
    if (eFnd != facesPerEdge.end())
    {
        if (eFnd() == 2)
        {
            return false;
        }
        eFnd()++;
    }
    else
    {
        facesPerEdge.insert(e, 1);
    }
    return true;
}
Пример #24
0
    bool findDfsVertexPathMarkingRec(vector<Vertex*> &path, const Vertex *end)
    {
        Vertex *lastVert = path.back();
        if (lastVert == end)
            return  true;

        if (mEdges.find(lastVert) != mEdges.end()) {
            VertSet *nexts = mEdges.at(lastVert);
            for (VertSet::iterator it = nexts->begin(); it != nexts->end(); ++it) {
                Vertex *vert = *it;
                if (mMarks.find(vert) == mMarks.end()) {
                    mMarks.insert(vert);
                    path.push_back(vert);
                    bool found = findDfsVertexPathMarkingRec(path, end);
                    if ( found )
                        return found;
                    else
                        path.pop_back();
                }
            }
        }
        return false;
    }
Пример #25
0
/**
 * Returns whether two vertices are connected in the graph.
 * @param u - one vertex
 * @param v - another vertex
 * @param functionName - the name of the calling function to return
 *  in the event of an error
 */
void Graph::assertConnected(Vertex u, Vertex v, string functionName) const
{
    EdgeMap uEdges = graph.at(u);
    if (uEdges.find(v) == uEdges.end())
        error(functionName + " called on unconnected vertices");

    EdgeMap vEdges = graph.at(v);
    if (vEdges.find(u) == vEdges.end())
        error(functionName + " called on unconnected vertices");
}
Пример #26
0
void facedeleter(){
    if(selectedFace >= 0){

	for(int i= selectedFace; i < numfaces-1 ; i++){
	    // basically assign it to the next face (can't delete last face though)
	    faxes[i].listEdge = faxes[i+1].listEdge;
	    faxes[i].ver = faxes[i+1].ver;
	    faxes[i].numedges = faxes[i+1].numedges;
	}
	faxes.pop_back(); // pop one out calling the destructor
	// delete pointers to this face
	for(int i = 0; i < faxes[selectedFace].numedges; i++){
	    Pair p(faxes[selectedFace].ver[(i+1) % (faxes[selectedFace].numedges)].id, faxes[selectedFace].ver[i].id);
	    EdgeMap::const_iterator iter;
	    iter = edgemap.find(p);
	    iter->second->thisface = NULL;
	}
	--numfaces;
	selectedFace = -1;
    }
}
Пример #27
0
void getAllIntersections(EdgeMap & map, float x, float y, float yaw, float fov, int nBeams, IntersectionMap & ms) {
    for(int i = 0; i<nBeams; i++) {
        float cBeamAngle = yaw + ((float)nBeams/2.0f - (float)i) * (fov / (float)nBeams);

        while(cBeamAngle < -M_PI) cBeamAngle += 2.0f*M_PI;
        while(cBeamAngle > M_PI) cBeamAngle -= 2.0f*M_PI;


        for(int j = 0; j<map.size(); j++) {
            float x0 = map[j].x0;
            float x1 = map[j].x1;
            float y0 = map[j].y0;
            float y1 = map[j].y1;
            float a = cBeamAngle;

			float d0 = - cos(a) * (y0+y1) + sin(a) * (x0 + x1);
			float d1 = (x1 + x) * (y0 + y1) - (y1 + y) * (x0 + x1);
			float d2 = -cos(a) * (y1 + y) + sin(a) * (x1 + x);

			float t = d1 / d0;
			float l = d2 / d0;

            if( l >= 0.0f && l <= 1.0f) {
                if(t > 0) {
                    Intersection iSect;
                    iSect.distance = t;
                    iSect.type = map[j].type;
                    iSect.offset = fmod((sqrt((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0)) * l) , map[j].texWidth);
                    ms[i].push_back(iSect);
                }
            }
        }

        std::sort(ms[i].begin(), ms[i].end(), sorter);

    }

}
Пример #28
0
void Foam::CV2D::extractPatches
(
    wordList& patchNames,
    labelList& patchSizes,
    EdgeMap<label>& mapEdgesRegion,
    EdgeMap<label>& indirectPatchEdge
) const
{
    label nPatches = qSurf_.patchNames().size() + 1;
    label defaultPatchIndex = qSurf_.patchNames().size();

    patchNames.setSize(nPatches);
    patchSizes.setSize(nPatches, 0);
    mapEdgesRegion.clear();

    const wordList& existingPatches = qSurf_.patchNames();

    forAll(existingPatches, sP)
    {
        patchNames[sP] = existingPatches[sP];
    }

    patchNames[defaultPatchIndex] = "CV2D_default_patch";

    for
    (
        Triangulation::Finite_edges_iterator eit = finite_edges_begin();
        eit != finite_edges_end();
        ++eit
    )
    {
        Face_handle fOwner = eit->first;
        Face_handle fNeighbor = fOwner->neighbor(eit->second);

        Vertex_handle vA = fOwner->vertex(cw(eit->second));
        Vertex_handle vB = fOwner->vertex(ccw(eit->second));

        if
        (
            (vA->internalOrBoundaryPoint() && !vB->internalOrBoundaryPoint())
         || (vB->internalOrBoundaryPoint() && !vA->internalOrBoundaryPoint())
        )
        {
            point ptA = toPoint3D(vA->point());
            point ptB = toPoint3D(vB->point());

            label patchIndex = qSurf_.findPatch(ptA, ptB);

            if (patchIndex == -1)
            {
                patchIndex = defaultPatchIndex;

                WarningInFunction
                    << "Dual face found that is not on a surface "
                    << "patch. Adding to CV2D_default_patch."
                    << endl;
            }

            edge e(fOwner->faceIndex(), fNeighbor->faceIndex());
            patchSizes[patchIndex]++;
            mapEdgesRegion.insert(e, patchIndex);

            if (!pointPair(*vA, *vB))
            {
                indirectPatchEdge.insert(e, 1);
            }
        }
    }
}
Пример #29
0
// ------------------------------------------------------------------------------------------------
// Note - this is an implementation of the standard (recursive) Cm-Cl algorithm without further
// optimizations (except we're using some nice LUTs). A description of the algorithm can be found
// here: http://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface
//
// The code is mostly O(n), however parts are O(nlogn) which is therefore the algorithm's
// expected total runtime complexity. The implementation is able to work in-place on the same
// mesh arrays. Calling #InternSubdivide() directly is not encouraged. The code can operate
// in-place unless 'smesh' and 'out' are equal (no strange overlaps or reorderings).
// Previous data is replaced/deleted then.
// ------------------------------------------------------------------------------------------------
void CatmullClarkSubdivider::InternSubdivide (
    const aiMesh* const * smesh,
    size_t nmesh,
    aiMesh** out,
    unsigned int num
    )
{
    ai_assert(NULL != smesh && NULL != out);
    INIT_EDGE_HASH_TEMPORARIES();

    // no subdivision requested or end of recursive refinement
    if (!num) {
        return;
    }

    UIntVector maptbl;
    SpatialSort spatial;

    // ---------------------------------------------------------------------
    // 0. Offset table to index all meshes continuously, generate a spatially
    // sorted representation of all vertices in all meshes.
    // ---------------------------------------------------------------------
    typedef std::pair<unsigned int,unsigned int> IntPair;
    std::vector<IntPair> moffsets(nmesh);
    unsigned int totfaces = 0, totvert = 0;
    for (size_t t = 0; t < nmesh; ++t) {
        const aiMesh* mesh = smesh[t];

        spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false);
        moffsets[t] = IntPair(totfaces,totvert);

        totfaces += mesh->mNumFaces;
        totvert  += mesh->mNumVertices;
    }

    spatial.Finalize();
    const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh));


#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second+vert_idx)
#define   FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first+face_idx)

    // ---------------------------------------------------------------------
    // 1. Compute the centroid point for all faces
    // ---------------------------------------------------------------------
    std::vector<Vertex> centroids(totfaces);
    unsigned int nfacesout = 0;
    for (size_t t = 0, n = 0; t < nmesh; ++t) {
        const aiMesh* mesh = smesh[t];
        for (unsigned int i = 0; i < mesh->mNumFaces;++i,++n)
        {
            const aiFace& face = mesh->mFaces[i];
            Vertex& c = centroids[n];

            for (unsigned int a = 0; a < face.mNumIndices;++a) {
                c += Vertex(mesh,face.mIndices[a]);
            }

            c /= static_cast<float>(face.mNumIndices);
            nfacesout += face.mNumIndices;
        }
    }

    {
    // we want edges to go away before the recursive calls so begin a new scope
    EdgeMap edges;

    // ---------------------------------------------------------------------
    // 2. Set each edge point to be the average of all neighbouring
    // face points and original points. Every edge exists twice
    // if there is a neighboring face.
    // ---------------------------------------------------------------------
    for (size_t t = 0; t < nmesh; ++t) {
        const aiMesh* mesh = smesh[t];

        for (unsigned int i = 0; i < mesh->mNumFaces;++i)   {
            const aiFace& face = mesh->mFaces[i];

            for (unsigned int p =0; p< face.mNumIndices; ++p) {
                const unsigned int id[] = {
                    face.mIndices[p],
                    face.mIndices[p==face.mNumIndices-1?0:p+1]
                };
                const unsigned int mp[] = {
                    maptbl[FLATTEN_VERTEX_IDX(t,id[0])],
                    maptbl[FLATTEN_VERTEX_IDX(t,id[1])]
                };

                Edge& e = edges[MAKE_EDGE_HASH(mp[0],mp[1])];
                e.ref++;
                if (e.ref<=2) {
                    if (e.ref==1) { // original points (end points) - add only once
                        e.edge_point = e.midpoint = Vertex(mesh,id[0])+Vertex(mesh,id[1]);
                        e.midpoint *= 0.5f;
                    }
                    e.edge_point += centroids[FLATTEN_FACE_IDX(t,i)];
                }
            }
        }
    }

    // ---------------------------------------------------------------------
    // 3. Normalize edge points
    // ---------------------------------------------------------------------
    {unsigned int bad_cnt = 0;
    for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) {
        if ((*it).second.ref < 2) {
            ai_assert((*it).second.ref);
            ++bad_cnt;
        }
        (*it).second.edge_point *= 1.f/((*it).second.ref+2.f);
    }

    if (bad_cnt) {
        // Report the number of bad edges. bad edges are referenced by less than two
        // faces in the mesh. They occur at outer model boundaries in non-closed
        // shapes.
        char tmp[512];
        ai_snprintf(tmp, 512, "Catmull-Clark Subdivider: got %u bad edges touching only one face (totally %u edges). ",
            bad_cnt,static_cast<unsigned int>(edges.size()));

        DefaultLogger::get()->debug(tmp);
    }}

    // ---------------------------------------------------------------------
    // 4. Compute a vertex-face adjacency table. We can't reuse the code
    // from VertexTriangleAdjacency because we need the table for multiple
    // meshes and out vertex indices need to be mapped to distinct values
    // first.
    // ---------------------------------------------------------------------
    UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(),0), ofsadjvec(maptbl.size()+1,0); {
    for (size_t t = 0; t < nmesh; ++t) {
        const aiMesh* const minp = smesh[t];
        for (unsigned int i = 0; i < minp->mNumFaces; ++i) {

            const aiFace& f = minp->mFaces[i];
            for (unsigned int n = 0; n < f.mNumIndices; ++n) {
                ++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]];
            }
        }
    }
    unsigned int cur = 0;
    for (size_t i = 0; i < cntadjfac.size(); ++i) {
        ofsadjvec[i+1] = cur;
        cur += cntadjfac[i];
    }
    for (size_t t = 0; t < nmesh; ++t) {
        const aiMesh* const minp = smesh[t];
        for (unsigned int i = 0; i < minp->mNumFaces; ++i) {

            const aiFace& f = minp->mFaces[i];
            for (unsigned int n = 0; n < f.mNumIndices; ++n) {
                faceadjac[ofsadjvec[1+maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t,i);
            }
        }
    }

    // check the other way round for consistency
#ifdef ASSIMP_BUILD_DEBUG

    for (size_t t = 0; t < ofsadjvec.size()-1; ++t) {
        for (unsigned int m = 0; m <  cntadjfac[t]; ++m) {
            const unsigned int fidx = faceadjac[ofsadjvec[t]+m];
            ai_assert(fidx < totfaces);
            for (size_t n = 1; n < nmesh; ++n) {

                if (moffsets[n].first > fidx) {
                    const aiMesh* msh = smesh[--n];
                    const aiFace& f = msh->mFaces[fidx-moffsets[n].first];

                    bool haveit = false;
                    for (unsigned int i = 0; i < f.mNumIndices; ++i) {
                        if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) {
                            haveit = true;
                            break;
                        }
                    }
                    ai_assert(haveit);
                    if (!haveit) {
                        DefaultLogger::get()->debug("Catmull-Clark Subdivider: Index not used");
                    }
                    break;
                }
            }
        }
    }

#endif
    }

#define GET_ADJACENT_FACES_AND_CNT(vidx,fstartout,numout) \
    fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx]

    typedef std::pair<bool,Vertex> TouchedOVertex;
    std::vector<TouchedOVertex > new_points(num_unique,TouchedOVertex(false,Vertex()));
    // ---------------------------------------------------------------------
    // 5. Spawn a quad from each face point to the corresponding edge points
    // the original points being the fourth quad points.
    // ---------------------------------------------------------------------
    for (size_t t = 0; t < nmesh; ++t) {
        const aiMesh* const minp = smesh[t];
        aiMesh* const mout = out[t] = new aiMesh();

        for (unsigned int a  = 0; a < minp->mNumFaces; ++a) {
            mout->mNumFaces += minp->mFaces[a].mNumIndices;
        }

        // We need random access to the old face buffer, so reuse is not possible.
        mout->mFaces = new aiFace[mout->mNumFaces];

        mout->mNumVertices = mout->mNumFaces*4;
        mout->mVertices = new aiVector3D[mout->mNumVertices];

        // quads only, keep material index
        mout->mPrimitiveTypes = aiPrimitiveType_POLYGON;
        mout->mMaterialIndex = minp->mMaterialIndex;

        if (minp->HasNormals()) {
            mout->mNormals = new aiVector3D[mout->mNumVertices];
        }

        if (minp->HasTangentsAndBitangents()) {
            mout->mTangents = new aiVector3D[mout->mNumVertices];
            mout->mBitangents = new aiVector3D[mout->mNumVertices];
        }

        for(unsigned int i = 0; minp->HasTextureCoords(i); ++i) {
            mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices];
            mout->mNumUVComponents[i] = minp->mNumUVComponents[i];
        }

        for(unsigned int i = 0; minp->HasVertexColors(i); ++i) {
            mout->mColors[i] = new aiColor4D[mout->mNumVertices];
        }

        mout->mNumVertices = mout->mNumFaces<<2u;
        for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces;++i) {

            const aiFace& face = minp->mFaces[i];
            for (unsigned int a = 0; a < face.mNumIndices;++a)  {

                // Get a clean new face.
                aiFace& faceOut = mout->mFaces[n++];
                faceOut.mIndices = new unsigned int [faceOut.mNumIndices = 4];

                // Spawn a new quadrilateral (ccw winding) for this original point between:
                // a) face centroid
                centroids[FLATTEN_FACE_IDX(t,i)].SortBack(mout,faceOut.mIndices[0]=v++);

                // b) adjacent edge on the left, seen from the centroid
                const Edge& e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
                    maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a==face.mNumIndices-1?0:a+1])
                    ])];  // fixme: replace with mod face.mNumIndices?

                // c) adjacent edge on the right, seen from the centroid
                const Edge& e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
                    maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[!a?face.mNumIndices-1:a-1])
                    ])];  // fixme: replace with mod face.mNumIndices?

                e0.edge_point.SortBack(mout,faceOut.mIndices[3]=v++);
                e1.edge_point.SortBack(mout,faceOut.mIndices[1]=v++);

                // d= original point P with distinct index i
                // F := 0
                // R := 0
                // n := 0
                // for each face f containing i
                //    F := F+ centroid of f
                //    R := R+ midpoint of edge of f from i to i+1
                //    n := n+1
                //
                // (F+2R+(n-3)P)/n
                const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])];
                TouchedOVertex& ov = new_points[org];

                if (!ov.first) {
                    ov.first = true;

                    const unsigned int* adj; unsigned int cnt;
                    GET_ADJACENT_FACES_AND_CNT(org,adj,cnt);

                    if (cnt < 3) {
                        ov.second = Vertex(minp,face.mIndices[a]);
                    }
                    else {

                        Vertex F,R;
                        for (unsigned int o = 0; o < cnt; ++o) {
                            ai_assert(adj[o] < totfaces);
                            F += centroids[adj[o]];

                            // adj[0] is a global face index - search the face in the mesh list
                            const aiMesh* mp = NULL;
                            size_t nidx;

                            if (adj[o] < moffsets[0].first) {
                                mp = smesh[nidx=0];
                            }
                            else {
                                for (nidx = 1; nidx<= nmesh; ++nidx) {
                                    if (nidx == nmesh ||moffsets[nidx].first > adj[o]) {
                                        mp = smesh[--nidx];
                                        break;
                                    }
                                }
                            }

                            ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces);
                            const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first];
                            bool haveit = false;

                            // find our original point in the face
                            for (unsigned int m = 0; m < f.mNumIndices; ++m) {
                                if (maptbl[FLATTEN_VERTEX_IDX(nidx,f.mIndices[m])] == org) {

                                    // add *both* edges. this way, we can be sure that we add
                                    // *all* adjacent edges to R. In a closed shape, every
                                    // edge is added twice - so we simply leave out the
                                    // factor 2.f in the amove formula and get the right
                                    // result.

                                    const Edge& c0 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
                                        nidx,f.mIndices[!m?f.mNumIndices-1:m-1])])];
                                    // fixme: replace with mod face.mNumIndices?

                                    const Edge& c1 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
                                        nidx,f.mIndices[m==f.mNumIndices-1?0:m+1])])];
                                    // fixme: replace with mod face.mNumIndices?
                                    R += c0.midpoint+c1.midpoint;

                                    haveit = true;
                                    break;
                                }
                            }

                            // this invariant *must* hold if the vertex-to-face adjacency table is valid
                            ai_assert(haveit);
                            if ( !haveit ) {
                                DefaultLogger::get()->warn( "OBJ: no name for material library specified." );
                            }
                        }

                        const float div = static_cast<float>(cnt), divsq = 1.f/(div*div);
                        ov.second = Vertex(minp,face.mIndices[a])*((div-3.f) / div) + R*divsq + F*divsq;
                    }
                }
                ov.second.SortBack(mout,faceOut.mIndices[2]=v++);
            }
        }
    }
    }  // end of scope for edges, freeing its memory

    // ---------------------------------------------------------------------
    // 7. Apply the next subdivision step.
    // ---------------------------------------------------------------------
    if (num != 1) {
        std::vector<aiMesh*> tmp(nmesh);
        InternSubdivide (out,nmesh,&tmp.front(),num-1);
        for (size_t i = 0; i < nmesh; ++i) {
            delete out[i];
            out[i] = tmp[i];
        }
    }
}
Пример #30
0
int main() {


	cv::namedWindow("render", cv::WINDOW_NORMAL);

//	cv::Mat map = cv::imread("test_map.bmp", cv::IMREAD_GRAYSCALE);

    EdgeMap map;

/*
map.push_back(Edge(-9.950000f, 8.350000f, -0.400000f, -8.300000f, 150));
map.push_back(Edge(-0.400000f, -8.300000f, 12.400000f, 4.100000f, 150));
map.push_back(Edge(12.400000f, 4.100000f, 1.000000f, 1.800000f, 150));
map.push_back(Edge(1.000000f, 1.800000f, -9.950000f, 8.350000f, 150));
*/
    map.push_back(Edge(10.0f, 10.0f, 10.0f, -10.0f, 100));
    map.push_back(Edge(10.0f, -10.0f, 1.0f, -1.0f, 100));
	
    map.push_back(Edge(1.0f, -1.0f, -10.0f, -10.0f, 100));

    map.push_back(Edge(-10.0f, -10.0f, -10.0f, 10.0f, 100));
    map.push_back(Edge(-10.0f, 10.0f, 10.0f, 10.0f, 100));

    int wndWidth = 1440;
	int wndHeight = 900;

	cv::Mat render(wndHeight,wndWidth, CV_8UC3);

	float df = 0.0f;
	float ds = 0.0f;
	float x = 0.0f;
    float y = 0.0f;
	float angle = -M_PI/2.0f;
	float dangle = 0.3f;
	float fov = M_PI/3.0f;

    std::vector<Sprite> sprites;

    Sprite ballSprite;
//    ballSprite.states.push_back(cv::imread("svidetel.jpg"));
//    ballSprite.x = 32;
//    ballSprite.y = -32;
//    ballSprite.width = 2;
    sprites.push_back(ballSprite);

    Texpack texpack;
    texpack[50] = Texture(cv::imread("wall_window.bmp"));
    texpack[100] = Texture(cv::imread("wood_wall.jpeg"));
    texpack[150] = Texture(cv::imread("brick_wall.jpeg"));
    texpack[200] = Texture(cv::imread("doom_door.jpeg"));

    for(int i = 1; i<15; i++) {
        char buf[1000];
        sprintf(buf,"doom_door_%d.jpg", i);
        texpack[200].addFrame(cv::imread(buf));
    }
    for(int i = 14; i>0; i--) {
        char buf[1000];
        sprintf(buf,"doom_door_%d.jpg", i);
        texpack[200].addFrame(cv::imread(buf));
    }

    texpack[200].animationTime = 2;
    texpack[200].animationType = Texture::ANIMATION_FRAMES;

	cv::Mat bgImageRaw = cv::imread("bg.png");
	cv::Mat bgImage;
	cv::resize(bgImageRaw, bgImage, cv::Size(2.0f*M_PI*(float)wndWidth/fov,wndHeight));

	double prevTime = getTime();
	while(1) {

        double cTime = getTime();

        animateTextures(texpack, cTime);

        calcNewPosition(map, x, y, angle, df, ds, dangle, cTime - prevTime);

        moveSprites(sprites);

        prevTime = cTime;

        newRenderAt(render, map, bgImage, fov, wndWidth, texpack, sprites, x, y, angle);
		cv::imshow("render",render);

/*
        cv::Mat mapD;
        cv::resize(map, mapD, cv::Size(640,640), 0, 0, cv::INTER_NEAREST);
        cv::line(mapD, cv::Point(x*10.0f,-y*10.0f), cv::Point(x + cos(-angle - fov/2.0f)*1000, y + sin(-angle - fov/2.0f)*1000)*10.0f, cv::Scalar(0,255,0,0),1);
        cv::line(mapD, cv::Point(x*10.0f,-y*10.0f), cv::Point(x + cos(-angle + fov/2.0f)*1000, y + sin(-angle + fov/2.0f)*1000)*10.0f, cv::Scalar(0,255,0,0),1);
        cv::imshow("map", mapD);
*/

        int k = cv::waitKey(1);

		if((char)k == 'q') {
			break;
		} else if((char)k == ',') {
            ds = 5.0f;
		} else if((char)k == '.') {
            ds = -5.0f;
		} else if((char)k == 'a') {
            dangle = +1.0f;
		} else if((char)k == 'd') {
            dangle = -1.0f;
		} else if((char)k == 's') {
            df = -5.0f;
		} else if((char)k == 'w') {
            df = 5.0f;
		} else if((char)k == '[') {
			fov -= M_PI/180.0f;
            //myLidar = VirtualLidar(fov, render.cols, 0);
		} else if((char)k == ']') {
			fov += M_PI/180.0f;
            //myLidar = VirtualLidar(fov, render.cols, 0);
		} else if((char)k == 'e'){
			ds = 0;
			df = 0;
			dangle = 0;
		} else {

            if(df > 1)
                df -= 5;
            else if(df < -1)
                df += 5;
            else
                df = 0;

            if(ds > 1)
                ds -= 5;
            else if(ds < -1)
                ds += 5;
            else
                ds = 0;

            if(dangle > 0.5f) {
                dangle -= 1.0f;
            } else if(dangle < -0.5f) {
                dangle += 1.0f;
            } else {
                dangle = 0;
            }
		}

	}
	return 0;
}