Пример #1
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;
}
Пример #2
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;
    }	
}
Пример #3
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));
        }
    }
}
Пример #4
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];
        }
    }
}
Пример #5
0
void ShadowMesh::decoupleEdges(EdgeMap& edges)
{
	vector<float> newVertices;
	EdgeMap newEdges;

	for (EdgeMapIterator it = edges.begin() ; it != edges.end() ; it++) {
		for (map<uint32_t, EdgeInfo>::iterator iit = it->second.begin() ; iit != it->second.end() ; iit++) {
			uint32_t idx1 = it->first;
			uint32_t idx2 = iit->first;

			EdgeInfo& info = iit->second;

			if (info.faceIndices.size() > 2) {
				// More than two faces on an edge. We will decouple them here

				vector<EdgeInfo::FaceInfo>::iterator idxIt = info.faceIndices.begin();
				vector<EdgeInfo::FaceInfo>::iterator nextIdxIt;
				idxIt++; idxIt++;

				for (; idxIt != info.faceIndices.end() ; idxIt++) {
					EdgeInfo::FaceInfo& finfo = *idxIt;
					uint32_t faceIdx = finfo.index;

					uint32_t newIdx1 = numVertices + newVertices.size()/3;
					float v11 = vertices[idx1*3];
					float v12 = vertices[idx1*3 + 1];
					float v13 = vertices[idx1*3 + 2];
					newVertices.push_back(v11);
					newVertices.push_back(v12);
					newVertices.push_back(v13);

					uint32_t newIdx2 = newIdx1+1;
					float v21 = vertices[idx2*3];
					float v22 = vertices[idx2*3 + 1];
					float v23 = vertices[idx2*3 + 2];
					newVertices.push_back(v21);
					newVertices.push_back(v22);
					newVertices.push_back(v23);

					EdgeInfo& newInfo = newEdges[newIdx2][newIdx1];
					newInfo.faceIndices.push_back(finfo);

					if (indices[faceIdx*3] == idx1) {
						indices[faceIdx*3] = newIdx1;

						if (indices[faceIdx*3 + 1] == idx2)
							indices[faceIdx*3 + 1] = newIdx2;
						else
							indices[faceIdx*3 + 2] = newIdx2;
					} else if (indices[faceIdx*3 + 1] == idx1) {
						indices[faceIdx*3 + 1] = newIdx1;

						if (indices[faceIdx*3] == idx2)
							indices[faceIdx*3] = newIdx2;
						else
							indices[faceIdx*3 + 2] = newIdx2;
					} else {
						indices[faceIdx*3 + 2] = newIdx1;

						if (indices[faceIdx*3] == idx2)
							indices[faceIdx*3] = newIdx2;
						else
							indices[faceIdx*3 + 1] = newIdx2;
					}

					nextIdxIt = idxIt;
					nextIdxIt++;

					if (nextIdxIt != info.faceIndices.end()) {
						// There's another face too much. This is true if we have an even number of faces on
						// this edge. In this case, we can group two of them together on a new edge so we
						// do not introduce any new cracks.

						EdgeInfo::FaceInfo& nextfInfo = *nextIdxIt;
						uint32_t nextFaceIdx = nextfInfo.index;

						newInfo.faceIndices.push_back(nextfInfo);

						if (indices[nextFaceIdx*3] == idx1) {
							indices[nextFaceIdx*3] = newIdx1;

							if (indices[nextFaceIdx*3 + 1] == idx2)
								indices[nextFaceIdx*3 + 1] = newIdx2;
							else
								indices[nextFaceIdx*3 + 2] = newIdx2;
						} else if (indices[nextFaceIdx*3 + 1] == idx1) {
							indices[nextFaceIdx*3 + 1] = newIdx1;

							if (indices[nextFaceIdx*3] == idx2)
								indices[nextFaceIdx*3] = newIdx2;
							else
								indices[nextFaceIdx*3 + 2] = newIdx2;
						} else {
							indices[nextFaceIdx*3 + 2] = newIdx1;

							if (indices[nextFaceIdx*3] == idx2)
								indices[nextFaceIdx*3] = newIdx2;
							else
								indices[nextFaceIdx*3 + 1] = newIdx2;
						}

						info.faceIndices.erase(nextIdxIt);
					}

					vector<EdgeInfo::FaceInfo>::iterator idxItCpy = idxIt;
					idxIt--;
					info.faceIndices.erase(idxItCpy);
				}
			}
		}
	}

	for (EdgeMapIterator it = newEdges.begin() ; it != newEdges.end() ; it++) {
		for (map<uint32_t, EdgeInfo>::iterator iit = it->second.begin() ; iit != it->second.end() ; iit++) {
			edges[it->first][iit->first] = iit->second;
		}
	}

	float* newVertexArr = new float[numVertices*3 + newVertices.size()];
	memcpy(newVertexArr, vertices, numVertices*3*sizeof(float));
	//copy(newVertices.begin(), newVertices.end(), newVertexArr + numVertices*3);

	for (uint32_t i = 0 ; i < newVertices.size() ; i++) {
		newVertexArr[numVertices*3 + i] = newVertices[i];
	}

	delete[] vertices;
	vertices = newVertexArr;

	numVertices += newVertices.size() / 3;
}
Пример #6
0
void ShadowMesh::calculateMissingData()
{
	EdgeMap edges;

	faceNormals = new float[numFaces*3];

	for (uint32_t i = 0 ; i < numFaces ; i++) {
		uint32_t idx1 = indices[i*3];
		uint32_t idx2 = indices[i*3 + 1];
		uint32_t idx3 = indices[i*3 + 2];

		Vector3& v1 = *((Vector3*) (vertices + idx1 * 3));
		Vector3& v2 = *((Vector3*) (vertices + idx2 * 3));
		Vector3& v3 = *((Vector3*) (vertices + idx3 * 3));

		Vector3 normal = (v2-v1).cross(v3-v1);
		memcpy(faceNormals + i*3, &normal, 3*sizeof(float));

		uint32_t e1Idx1, e1Idx2;
		uint32_t e2Idx1, e2Idx2;
		uint32_t e3Idx1, e3Idx2;

		if (idx1 > idx2) {
			e1Idx1 = idx1;
			e1Idx2 = idx2;
		} else {
			e1Idx1 = idx2;
			e1Idx2 = idx1;
		}

		if (idx2 > idx3) {
			e2Idx1 = idx2;
			e2Idx2 = idx3;
		} else {
			e2Idx1 = idx3;
			e2Idx2 = idx2;
		}

		if (idx3 > idx1) {
			e3Idx1 = idx3;
			e3Idx2 = idx1;
		} else {
			e3Idx1 = idx1;
			e3Idx2 = idx3;
		}

		EdgeInfo& e1Info = edges[e1Idx1][e1Idx2];
		EdgeInfo::FaceInfo e1fInfo;
		e1fInfo.index = i;
		e1fInfo.additionalIndex = 2;
		e1Info.faceIndices.push_back(e1fInfo);

		EdgeInfo& e2Info = edges[e2Idx1][e2Idx2];
		EdgeInfo::FaceInfo e2fInfo;
		e2fInfo.index = i;
		e2fInfo.additionalIndex = 0;
		e2Info.faceIndices.push_back(e2fInfo);

		EdgeInfo& e3Info = edges[e3Idx1][e3Idx2];
		EdgeInfo::FaceInfo e3fInfo;
		e3fInfo.index = i;
		e3fInfo.additionalIndex = 1;
		e3Info.faceIndices.push_back(e3fInfo);
	}

	bool decoupled = false;
	for (ConstEdgeMapIterator it = edges.begin() ; it != edges.end()  &&  !decoupled ; it++) {
		for (map<uint32_t, EdgeInfo>::const_iterator iit = it->second.begin() ; iit != it->second.end() ; iit++) {
			const EdgeInfo& info = iit->second;

			if (info.faceIndices.size() > 2) {
				decoupleEdges(edges);
				decoupled = true;
				break;
			}
		}
	}


	float* extendedVertices = new float[2*numVertices * 4];

	for (uint32_t i = 0 ; i < numVertices ; i++) {
		memcpy(extendedVertices + i*4, vertices + i*3, 3*sizeof(float));
		extendedVertices[i*4 + 3] = 1.0f;
	}
	for (uint32_t i = 0 ; i < numVertices ; i++) {
		memcpy(extendedVertices + (numVertices+i)*4, vertices + i*3, 3*sizeof(float));
		extendedVertices[(numVertices+i)*4 + 3] = 0.0f;
	}

	delete[] vertices;
	vertices = extendedVertices;


	uint32_t* extendedIndices = new uint32_t[numFaces*6];

	// Enter the base indices for all faces into extendedIndices
	for (uint32_t i = 0 ; i < numFaces ; i++) {
		extendedIndices[i*6] = indices[i*3];
		extendedIndices[i*6 + 2] = indices[i*3 + 1];
		extendedIndices[i*6 + 4] = indices[i*3 + 2];
	}

	uint32_t dummyIdx = numVertices*2 - 1;

	adjacentFaces = new uint32_t[numFaces*3];

	for (EdgeMapIterator it = edges.begin() ; it != edges.end() ; it++) {
		uint32_t idx1 = it->first;

		for (map<uint32_t, EdgeInfo>::iterator iit = it->second.begin() ; iit != it->second.end() ; iit++) {
			uint32_t idx2 = iit->first;

			EdgeInfo& info = iit->second;

			EdgeInfo::FaceInfo& f1 = info.faceIndices[0];
			uint32_t f1ExtendedAdditionalIdx = f1.index*6 + (2*f1.additionalIndex + 3) % 6;

			if (info.faceIndices.size() == 1) {
				// f1 has no adjacent face between idx1 and idx2

				extendedIndices[f1ExtendedAdditionalIdx] = dummyIdx;

				// This value is invalid and shall not be used when there is no adjacent face, so we can
				// basically set it to anything we want
				adjacentFaces[f1.index*3 + (f1.additionalIndex+1) % 3] = 0;
			} else {
				// There are two adjacent faces on edge idx1-idx2

				EdgeInfo::FaceInfo& f2 = info.faceIndices[1];
				uint32_t f2ExtendedAdditionalIdx = f2.index*6 + (2*f2.additionalIndex + 3) % 6;

				extendedIndices[f1ExtendedAdditionalIdx] = indices[f2.index*3 + f2.additionalIndex];
				extendedIndices[f2ExtendedAdditionalIdx] = indices[f1.index*3 + f1.additionalIndex];

				adjacentFaces[f1.index*3 + (f1.additionalIndex+1) % 3] = f2.index;
				adjacentFaces[f2.index*3 + (f2.additionalIndex+1) % 3] = f1.index;
			}
		}
	}

	delete[] indices;
	indices = extendedIndices;
}
Пример #7
0
//----------------------------------------------------------------------------
CreateEnvelope::CreateEnvelope (int numVertices, const Vector2f* vertices,
                                int numIndices, const int* indices, int& numEnvelopeVertices,
                                Vector2f*& envelopeVertices)
{
	// The graph of vertices and edgeMaps to be used for constructing the
	// obstacle envelope.
	SegmentGraph* graph = new0 SegmentGraph();

	// Convert the vertices to rational points to allow exact arithmetic,
	// thereby avoiding problems with numerical round-off errors.
	RPoint2* ratVertices = new1<RPoint2>(numVertices);
	int i;
	for (i = 0; i < numVertices; ++i)
	{
		ratVertices[i].X() = RScalar(vertices[i].X());
		ratVertices[i].Y() = RScalar(vertices[i].Y());
	}

	// Insert the 2D mesh edgeMaps into the graph.
	const int* currentIndex = indices;
	int numTriangles = numIndices/3;
	for (i = 0; i < numTriangles; ++i)
	{
		int v0 = *currentIndex++;
		int v1 = *currentIndex++;
		int v2 = *currentIndex++;
		graph->InsertEdge(ratVertices[v0], ratVertices[v1]);
		graph->InsertEdge(ratVertices[v1], ratVertices[v2]);
		graph->InsertEdge(ratVertices[v2], ratVertices[v0]);
	}
	delete1(ratVertices);

	// Represent each edge as a map of points ordered by rational parameter
	// values, each point P(t) = End0 + t*(End1-End0), where End0 and End1
	// are the rational endpoints of the edge and t is the rational
	// parameter for the edge point P(t).
	std::set<SegmentGraph::Edge>& edgeSet = graph->GetEdges();
	int numEdges = (int)edgeSet.size();
	EdgeMap** edgeMaps = new1<EdgeMap*>(numEdges);
	std::set<SegmentGraph::Edge>::iterator esIter = edgeSet.begin();
	for (i = 0; i < numEdges; ++i, ++esIter)
	{
		SegmentGraph::Edge edge = *esIter;
		EdgeMap* edgeMap = new0 EdgeMap();
		(*edgeMap)[0] = edge.GetVertex(0)->Position;
		(*edgeMap)[1] = edge.GetVertex(1)->Position;
		edgeMaps[i] = edgeMap;
	}

	UpdateAllEdges(numEdges, edgeMaps);

	// Recreate the graph, now using the segmented edgeMaps from the original
	// graph.
	delete0(graph);
	graph = new0 SegmentGraph();
	for (i = 0; i < numEdges; ++i)
	{
		// Each graph edge is a pair of consecutive edge points.
		EdgeMap* edgeMap = edgeMaps[i];

		// Get first point.
		EdgeMap::iterator iter = edgeMap->begin();
		EdgeMap::iterator end = edgeMap->end();
		RPoint2* point0 = &iter->second;

		// Get remaining points.
		for (++iter; iter != end; ++iter)
		{
			RPoint2* point1 = &iter->second;
			graph->InsertEdge(*point0, *point1);
			point0 = point1;
		}

		delete0(edgeMap);
	}
	delete1(edgeMaps);

	std::vector<RPoint2> envelope;
	graph->ExtractEnvelope(envelope);

	// Convert the vertices back to floating-point values and return to the
	// caller.
	numEnvelopeVertices = (int)envelope.size();
	envelopeVertices = new1<Vector2f>(numEnvelopeVertices);
	for (i = 0; i < numEnvelopeVertices; ++i)
	{
		const RPoint2& point = envelope[i];
		point.X().ConvertTo(envelopeVertices[i].X());
		point.Y().ConvertTo(envelopeVertices[i].Y());
	}

	delete0(graph);
}