Beispiel #1
0
void Atlas::extractCharts()
{
    const uint faceCount = m_mesh->faceCount();

    int first = 0;
    Array<uint> queue(faceCount);

    BitArray bitFlags(faceCount);
    bitFlags.clearAll();

    for (uint f = 0; f < faceCount; f++)
    {
        if (bitFlags.bitAt(f) == false)
        {
            // Start new patch. Reset queue.
            first = 0;
            queue.clear();
            queue.append(f);
            bitFlags.setBitAt(f);

            while (first != queue.count())
            {
                const HalfEdge::Face * face = m_mesh->faceAt(queue[first]);

                // Visit face neighbors of queue[first]
                for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
                {
                    const HalfEdge::Edge * edge = it.current();
                    nvDebugCheck(edge->pair != NULL);

                    if (!edge->isBoundary() && /*!edge->isSeam()*/ 
                        //!(edge->from()->tex() != edge->pair()->to()->tex() || edge->to()->tex() != edge->pair()->from()->tex()))
                        !(edge->from() != edge->pair->to() || edge->to() != edge->pair->from())) // Preserve existing seams (not just texture seams).
                    {
                        const HalfEdge::Face * neighborFace = edge->pair->face;
                        nvDebugCheck(neighborFace != NULL);

                        if (bitFlags.bitAt(neighborFace->id) == false)
                        {
                            queue.append(neighborFace->id);
                            bitFlags.setBitAt(neighborFace->id);
                        }
                    }
                }

                first++;
            }

            Chart * chart = new Chart();
            chart->build(m_mesh, queue);

            m_chartArray.append(chart);
        }
    }
}
Beispiel #2
0
void Atlas::computeCharts(const SegmentationSettings & settings)
{
    AtlasBuilder builder(m_mesh);

    // Tweak these values:
    const float maxThreshold = 2;
    const uint growFaceCount = 32;
    const uint maxIterations = 4;
    
    builder.settings = settings;

    //builder.settings.proxyFitMetricWeight *= 0.75; // relax proxy fit weight during initial seed placement.
    //builder.settings.roundnessMetricWeight = 0;
    //builder.settings.straightnessMetricWeight = 0;

    // This seems a reasonable estimate.
    uint maxSeedCount = max(6U, m_mesh->faceCount());

    // Create initial charts greedely.
    nvDebug("### Placing seeds\n");
    builder.placeSeeds(maxThreshold, maxSeedCount);
    nvDebug("###   Placed %d seeds (max = %d)\n", builder.chartCount(), maxSeedCount);

    builder.updateProxies();

    builder.mergeCharts();

#if 1
    nvDebug("### Relocating seeds\n");
    builder.relocateSeeds();

    nvDebug("### Reset charts\n");
    builder.resetCharts();

    builder.settings = settings;

    nvDebug("### Growing charts\n");

    // Restart process growing charts in parallel.
    uint iteration = 0;
    while (true)
    {
        if (!builder.growCharts(maxThreshold, growFaceCount))
        {
            nvDebug("### Can't grow anymore\n");

            // If charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.

            nvDebug("### Filling holes\n");
            builder.fillHoles(maxThreshold);
            nvDebug("###   Using %d charts now\n", builder.chartCount());

            builder.updateProxies();

            nvDebug("### Merging charts\n");
            builder.mergeCharts();
            nvDebug("###   Using %d charts now\n", builder.chartCount());

            nvDebug("### Reseeding\n");
            if (!builder.relocateSeeds())
            {
                nvDebug("### Cannot relocate seeds anymore\n");

                // Done!
                break;
            }

            if (iteration == maxIterations)
            {
                nvDebug("### Reached iteration limit\n");
                break;
            }
            iteration++;

            nvDebug("### Reset charts\n");
            builder.resetCharts();

            nvDebug("### Growing charts\n");
        }
    };
#endif

    // Make sure no holes are left!
    nvDebugCheck(builder.facesLeft == 0);

    const uint chartCount = builder.chartArray.count();
    for (uint i = 0; i < chartCount; i++)
    {
        Chart * chart = new Chart();
        m_chartArray.append(chart);

        chart->build(m_mesh, builder.chartFaces(i));
    }

    // Build face indices.
    m_faceChart.resize(m_mesh->faceCount());
    m_faceIndex.resize(m_mesh->faceCount());

    for (uint i = 0; i < chartCount; i++)
    {
        const Chart * chart = m_chartArray[i];

        const uint faceCount = chart->faceCount();
        for (uint f = 0; f < faceCount; f++)
        {
            uint idx = chart->faceAt(f);
            m_faceChart[idx] = i;
            m_faceIndex[idx] = f;
        }
    }

    // Build an exclusive prefix sum of the chart vertex counts.
    m_chartVertexCountPrefixSum.resize(chartCount);
    
    if (chartCount > 0)
    {
        m_chartVertexCountPrefixSum[0] = 0;
        
        for (uint i = 1; i < chartCount; i++)
        {
            const Chart * chart = m_chartArray[i-1];
            m_chartVertexCountPrefixSum[i] = m_chartVertexCountPrefixSum[i-1] + chart->vertexCount();
        }

        m_totalVertexCount = m_chartVertexCountPrefixSum[chartCount - 1] + m_chartArray[chartCount-1]->vertexCount();
    }
    else
    {
        m_totalVertexCount = 0;
    }
   
}