Program Listing for File IndexedFaceMesh.cpp

Return to documentation for file (Utils/IndexedFaceMesh.cpp)

#include "IndexedFaceMesh.h"

using namespace Utilities;

IndexedFaceMesh& IndexedFaceMesh::operator=(IndexedFaceMesh const& other)
{
    m_numPoints        = other.m_numPoints;
    m_indices          = other.m_indices;
    m_edges            = other.m_edges;
    m_facesEdges       = other.m_facesEdges;
    m_closed           = other.m_closed;
    m_uvIndices = other.m_uvIndices;
    m_uvs = other.m_uvs;
    m_normals          = other.m_normals;
    m_vertexNormals    = other.m_vertexNormals;

    for (size_t i(0u); i < m_facesEdges.size(); ++i)
    {
        m_facesEdges[i].resize(m_verticesPerFace);
#if defined(_MSC_VER)
        std::copy(other.m_facesEdges[i].data(), other.m_facesEdges[i].data() + m_verticesPerFace,
            stdext::unchecked_array_iterator<unsigned int*>(m_facesEdges[i].data()));
#else
        std::copy(other.m_facesEdges[i].data(), other.m_facesEdges[i].data() + m_verticesPerFace, m_facesEdges[i].data());
#endif
    }

    m_verticesEdges.resize(other.m_verticesEdges.size());
    for (size_t i(0u); i < m_verticesEdges.size(); ++i)
        m_verticesEdges[i] = other.m_verticesEdges[i];

    m_verticesFaces.resize(other.m_verticesFaces.size());
    for (size_t i(0u); i < m_verticesFaces.size(); ++i)
        m_verticesFaces[i] = other.m_verticesFaces[i];

    return *this;
}

IndexedFaceMesh::IndexedFaceMesh(IndexedFaceMesh const& other)
{
    *this = other;
}

IndexedFaceMesh::IndexedFaceMesh()
{
    m_closed=false;
    m_flatShading = false;
    m_numPoints = 0;
}

IndexedFaceMesh::~IndexedFaceMesh()
{
    release();
}

bool IndexedFaceMesh::isClosed() const
{
    return m_closed;
}

void IndexedFaceMesh::initMesh(const unsigned int nPoints, const unsigned int nEdges, const unsigned int nFaces)
{
    m_numPoints = nPoints;
    m_indices.reserve(nFaces*m_verticesPerFace);
    m_edges.reserve(nEdges);
    m_facesEdges.reserve(nFaces);
    m_uvIndices.reserve(nFaces);
    m_uvs.reserve(nPoints);
    m_verticesFaces.reserve(nPoints);
    m_verticesEdges.reserve(nPoints);
    m_normals.reserve(nFaces);
    m_vertexNormals.reserve(nPoints);
}

void IndexedFaceMesh::release()
{
    m_indices.clear();
    m_edges.clear();
    m_facesEdges.clear();
    m_facesEdges.clear();
    m_uvIndices.clear();
    m_uvs.clear();
    m_verticesFaces.clear();
    m_verticesEdges.clear();
    m_normals.clear();
    m_vertexNormals.clear();
}

void IndexedFaceMesh::addFace(const unsigned int * const indices)
{
    for (unsigned int i=0u; i < m_verticesPerFace; i++)
        m_indices.push_back(indices[i]);
}

void IndexedFaceMesh::addFace(const int * const indices)
{
    for (unsigned int i=0u; i < m_verticesPerFace; i++)
        m_indices.push_back((unsigned int) indices[i]);
}

void IndexedFaceMesh::addUV(const Real u, const Real v)
{
    Vector2r uv;
    uv[0] = u;
    uv[1] = v;
    m_uvs.push_back(uv);
}

void IndexedFaceMesh::addUVIndex(const unsigned int index)
{
    m_uvIndices.push_back(index);
}

void IndexedFaceMesh::buildNeighbors()
{
    typedef std::vector<unsigned int> PEdges;

    PEdges* pEdges = new PEdges[numVertices()];

    // build vertex-face structure
    m_verticesFaces.clear(); // to delete old pointers
    m_verticesFaces.resize(numVertices());
    m_verticesEdges.clear(); // to delete old pointers
    m_verticesEdges.resize(numVertices());
    m_facesEdges.clear();
    m_facesEdges.resize(numFaces());

    m_edges.clear();

    unsigned int *v = new unsigned int[m_verticesPerFace];
    unsigned int *edges = new unsigned int[m_verticesPerFace*2];
    for(unsigned int i=0; i < numFaces(); i++)
    {
        m_facesEdges[i].resize(m_verticesPerFace);
        for (unsigned int j=0u; j < m_verticesPerFace; j++)
            v[j] = m_indices[m_verticesPerFace*i+j];

        for (unsigned int j=0u; j < m_verticesPerFace-1u; j++)
        {
            edges[2*j] = v[j];
            edges[2*j+1] = v[j+1];
        }
        edges[2*(m_verticesPerFace-1)] = v[m_verticesPerFace-1];
        edges[2*(m_verticesPerFace-1)+1] = v[0];

        for(unsigned int j=0u; j < m_verticesPerFace; j++)
        {
            // add vertex-face connection
            const unsigned int vIndex = m_indices[m_verticesPerFace*i+j];
            bool found = false;
            for(unsigned int k=0; k < m_verticesFaces[vIndex].size(); k++)
            {
                if (m_verticesFaces[vIndex][k] == i)
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                m_verticesFaces[vIndex].push_back(i);
            }

            // add edge information
            const unsigned int a = edges[j*2+0];
            const unsigned int b = edges[j*2+1];
            unsigned int edge = 0xffffffff;
            // find edge
            for(unsigned int k=0; k < pEdges[a].size(); k++)
            {
                const Edge& e = m_edges[pEdges[a][k]];
                if(((e.m_vert[0] == a) || (e.m_vert[0] == b)) &&
                    ((e.m_vert[1] == a) || (e.m_vert[1] == b)))
                {
                    edge = pEdges[a][k];
                    break;
                }
            }
            if(edge == 0xffffffff)
            {
                // create new
                Edge e;
                e.m_vert[0] = a;
                e.m_vert[1] = b;
                e.m_face[0] = i;
                e.m_face[1] = 0xffffffff;
                m_edges.push_back(e);
                edge = (unsigned int) m_edges.size() - 1u;

                // add vertex-edge connection
                m_verticesEdges[a].push_back(edge);
                m_verticesEdges[b].push_back(edge);
            }
            else
            {
                Edge& e = m_edges[edge];
                e.m_face[1] = i;
            }
            // append to points
            pEdges[a].push_back(edge);
            pEdges[b].push_back(edge);
            // append face
            m_facesEdges[i][j] = edge;
        }
    }
    delete [] v;
    delete [] edges;

    // check for boundary
    m_closed = true;
    for (unsigned int i = 0; i < (unsigned int)m_edges.size(); i++)
    {
        Edge& e = m_edges[i];
        if(e.m_face[1] == 0xffffffff)
        {
            m_closed = false;
            break;
        }
    }

    delete [] pEdges;
}

void IndexedFaceMesh::copyUVs(const UVIndices& uvIndices, const UVs& uvs)
{
    m_uvs.clear();
    m_uvs.resize(uvs.size());

    for (unsigned int i = 0; i < uvs.size(); i++)
    {
        m_uvs[i] = uvs[i];
    }

    m_uvIndices.clear();
    m_uvIndices.resize(uvIndices.size());

    for (unsigned int i = 0; i < uvIndices.size(); i++)
    {
        m_uvIndices[i] = uvIndices[i];
    }
}

unsigned int IndexedFaceMesh::getVerticesPerFace() const
{
    return m_verticesPerFace;
}