Esempio n. 1
0
//=================================================================================================================================
/// Removes all the neighbors from a specified Face, with the exception of a specified neighbor
///
/// \param rFace The face to remove from its neighbors
/// \param pExceptNeighbor A neighbor from which rFace should not be removed
///
/// \return true
//=================================================================================================================================
bool FaceManager::DropNeighbors(Face& rFace, Face* pExceptNeighbor)
{
#ifdef _TIMING
    _TIME tStart = GetTime();
#endif
    // get all the neighbors
    Face** neighbors = rFace.GetNeighbors();

    // remove this face from the degree bins
    m_degreeBins[ rFace.Degree() ].remove(&rFace);

    Face* pNeighbor = NULL;

    // re-bin the neighbors
    for (unsigned int i = 0; i < 3; i++)
    {
        pNeighbor = neighbors[i];

        if (pNeighbor != NULL)
        {
            if (pNeighbor != pExceptNeighbor)
            {
                // Note that now the neighbors are only singly linked
                // the striped Face knows it's neighbors, but the neighbors
                // don't know the striped face.
                m_degreeBins[ pNeighbor->Degree() ].remove(pNeighbor);

                // push on the back so that if the algorithm needs to start a new strip
                // it is more likely to get a face whose vertex is already in the cache
                m_degreeBins[ pNeighbor->RemoveNeighbor(&rFace) ].push_back(pNeighbor);

                rFace.RemoveNeighbor(pNeighbor);
            }
        }
    }

#ifdef _TIMING
    m_tDropNeighbors += (GetTime() - tStart);
#endif

    return true;
}
Esempio n. 2
0
//=================================================================================================================================
/// Generates an efficient list from the previously created faces
///
/// \return true
//=================================================================================================================================
bool FaceManager::Stripify(void)
{
#ifdef _TIMING
    _TIME tStartStripify = GetTime();
#endif

    for (FaceRefList::iterator iFace = m_faces.begin(); iFace != m_faces.end(); iFace++)
    {
        m_degreeBins[(*iFace)->Degree() ].push_front(*iFace);
    }

#ifdef _TIMING
    m_tSortBins += (GetTime() - tStartStripify);
#endif

    UINT uWalkMode = START;
    UINT uFirstTurn = START;

    UINT nodesLeft = (UINT)m_faces.size();
    bool bFirstDirection = true;
    bool bRepeatedTurn = false;
    int stripIndex = -1;
    FaceStrips strips;
    Face* pCurFace = NULL;

    // variables that need to get declared before the switch statement
    Face* pNextFace = NULL;
    Face* pGateFace = NULL;
    UINT uGateEdge;
    UINT uBackEdge = 0;
    UINT uFirstEdge = 1;

    // make sure that the starting edge is in the 0-2 range
    uFirstEdge %= 3;

    while (nodesLeft > 0)
    {
        if (uWalkMode == START)
        {
            bFirstDirection = true;
            stripIndex++;
            strips.push_back(FaceStrip());

            pCurFace = NULL;

            // stop when a face with lowest degree is found
            // this means we'll start along edges and the strip will work its way inward
            // Provided good improvement (~10%)
            for (UINT uDegree = 0; uDegree < 4 && pCurFace == NULL; uDegree++)
            {
                if (m_degreeBins[uDegree].size() > 0)
                {
                    // pick a face that has not already been processed
                    for (FaceRefList::iterator iter = m_degreeBins[uDegree].begin();
                         iter != m_degreeBins[uDegree].end() && pCurFace == NULL;
                         iter++)
                    {
                        if (*iter != NULL && (*iter)->WasProcessed() == false)
                        {
                            pCurFace = *(iter);
                        }
                    }
                }
            }

            // first face has been chosen
            // now choose the direction to travel
            uGateEdge = uFirstEdge;
            pNextFace = NULL;
            UINT uLowestDegree = 4;

            for (UINT uEdge = 0; uEdge < 3; uEdge++)
            {
                // use GateFace as a temporary place holder
                pGateFace = pCurFace->GetNeighbors()[(uFirstEdge + uEdge) % 3 ];

                if (pGateFace != NULL && pGateFace->WasProcessed() == false)
                {
                    if (pGateFace->Degree() < uLowestDegree)
                    {
                        // make the next face the neighbor with the highest degree
                        uLowestDegree = pGateFace->Degree();
                        pNextFace = pGateFace;
                        uGateEdge = (uFirstEdge + uEdge) % 3;
                        uBackEdge = pNextFace->GetEdge(pCurFace);
                    }
                }
            }

            // Add first face in this strip
            AddFaceToStrip(pCurFace, strips[ stripIndex ], START, uGateEdge);
            nodesLeft--;

            if (pNextFace != NULL)
            {
                uWalkMode = LEFT;
                uFirstTurn = START;
            }
            else
            {
                // no next face found
                uWalkMode = FINISH;
            }
        } // end if uWalkMode == START

        if (uWalkMode == RIGHT)
        {
            UINT uEnterEdge = uBackEdge;
            pCurFace = pNextFace;
            pNextFace = NULL;
            uGateEdge = (uBackEdge + 1) % 3;
            pGateFace = pCurFace->GetNeighbors()[ uGateEdge ];

            if (pGateFace != NULL && pGateFace->WasProcessed() == false)
            {
                bRepeatedTurn = false;
                pNextFace = pGateFace;
                uBackEdge = pNextFace->GetEdge(pCurFace);
                uWalkMode = LEFT;

                if (uFirstTurn == START)
                {
                    uFirstTurn = RIGHT;
                }
            }
            else
            {
                // continuing to the right, need to indicate that it is a
                // repeated turn, so the output of the vertices should be different!
                bRepeatedTurn = true;
                uGateEdge = (uBackEdge + 2) % 3;
                pGateFace = pCurFace->GetNeighbors()[ uGateEdge ];

                if (pGateFace != NULL && pGateFace->WasProcessed() == false)
                {
                    pNextFace = pGateFace;
                    uBackEdge = pNextFace->GetEdge(pCurFace);

                    if (uFirstTurn == START)
                    {
                        uFirstTurn = LEFT;
                    }
                }
            }

            if (bRepeatedTurn)
            {
                AddFaceToStrip(pCurFace, strips[ stripIndex ], LEFT, uEnterEdge);
            }
            else
            {
                AddFaceToStrip(pCurFace, strips[ stripIndex ], RIGHT, uEnterEdge);
            }

            nodesLeft--;

            if (pNextFace == NULL)
            {
                uWalkMode = FINISH;
            }
        }
        else if (uWalkMode == LEFT)
        {
            UINT uEnterEdge = uBackEdge;
            pCurFace = pNextFace;
            pNextFace = NULL;
            uGateEdge = (uBackEdge + 2) % 3;
            pGateFace = pCurFace->GetNeighbors()[ uGateEdge ];

            if (pGateFace != NULL && pGateFace->WasProcessed() == false)
            {
                bRepeatedTurn = false;
                pNextFace = pGateFace;
                uBackEdge = pNextFace->GetEdge(pCurFace);
                uWalkMode = RIGHT;

                if (uFirstTurn == START)
                {
                    uFirstTurn = LEFT;
                }
            }
            else
            {
                // continuing to the left, need to indicate that it is a
                // repeated turn, so the output of the vertices should be different!
                bRepeatedTurn = true;
                uGateEdge = (uBackEdge + 1) % 3;
                pGateFace = pCurFace->GetNeighbors()[ uGateEdge ];

                if (pGateFace != NULL && pGateFace->WasProcessed() == false)
                {
                    pNextFace = pGateFace;
                    uBackEdge = pNextFace->GetEdge(pCurFace);

                    if (uFirstTurn == START)
                    {
                        uFirstTurn = RIGHT;
                    }
                }
            }

            if (bRepeatedTurn)
            {
                AddFaceToStrip(pCurFace, strips[ stripIndex ], RIGHT, uEnterEdge);
            }
            else
            {
                AddFaceToStrip(pCurFace, strips[ stripIndex ], LEFT, uEnterEdge);
            }

            nodesLeft--;

            if (pNextFace == NULL)
            {
                uWalkMode = FINISH;
            }
        }

        if (uWalkMode == FINISH)
        {
            bRepeatedTurn = false;
            uWalkMode = START;

            //int nStrips = strips.size() -1;
            //int nTris = strips[ nStrips ].size();
            //if ( nTris > 2 )
            //{
            //   printf( " %d,", nTris );
            //   printf( "\nRotated list:" );
            //   int nRecentVertsStart = m_vertList.size() - (nTris*3);
            //   for ( int i = nRecentVertsStart; i < m_vertList.size(); i+=3 )
            //   {
            //      printf( " %2d %2d %2d,", m_vertList[i], m_vertList[i+1], m_vertList[i+2] );
            //   }
            //   printf("\n");
            //}

        }
    }

    // At this point, the strips should have all the data in them,
    // the triangles are in a good strip order, but the vertices may
    // have to be rotated to make it have good 2 vertex cache reuse
    //for ( UINT i = 0; i < strips.size(); i++ )
    //{
    //   printf( "\nStrip %3d has %4d triangles:", i, strips[i].size() );
    //   for ( FaceStrip::iterator fsi = strips[i].begin(); fsi != strips[i].end(); fsi++ )
    //   {
    //      printf( " %2d %2d %2d,", (*fsi)->First(), (*fsi)->Second(), (*fsi)->Third() );
    //   }
    //}
    //printf( "\nRotated list:" );
    //for ( UINT i = 0; i < m_vertList.size(); i+=3 )
    //{
    //   printf( " %2d %2d %2d,", m_vertList[i], m_vertList[i+1], m_vertList[i+2] );
    //}
    //printf("\n");

#ifdef _TIMING
    m_tStripify = GetTime() - tStartStripify;
#endif

    return true;
}
Esempio n. 3
0
//=================================================================================================================================
/// Makes a Face from the specified vertex indices and associates it with neighbors that have already been created
///
/// \param uVertexIndex1 the first vertex index of the face
/// \param uVertexIndex2 the second vertex index of the face
/// \param uVertexIndex3 the third vertex index of the face
/// \param nID           the ID of the face
///
/// \return false if memory could not be allocated for the face; true otherwise
//=================================================================================================================================
bool FaceManager::MakeFace(UINT uVertexIndex1, UINT uVertexIndex2, UINT uVertexIndex3, UINT nID)
{
#ifdef _TIMING
    _TIME tMNStart;
    _TIME tAdjStart;

    tMNStart = GetTime();
#endif
    Face* pFace;

    try
    {
        pFace = new Face(uVertexIndex1, uVertexIndex2, uVertexIndex3);
    }
    catch (std::bad_alloc&)
    {
        // ran out of memory
        return false;
    }

#ifdef _TIMING
    m_tMakeNeighbors += GetTime() - tMNStart;

    tMNStart = GetTime();
#endif

    int nAdjacency = -1;
    Face* pIterFace = NULL;

    for (FaceRefList::iterator f = m_faces.begin(); f != m_faces.end() && pFace->Degree() < 3; f++)
    {
        pIterFace = *f;

        // finding adjacency is expensize, only do it if the face doesn't already have three neighbors
        if (pIterFace->Degree() < 3)
        {
#ifdef _TIMING
            tAdjStart = GetTime();
#endif
            nAdjacency = GetFaceAdjacency(*pFace, *pIterFace);

#ifdef _TIMING
            m_tAdjacency += (GetTime() - tAdjStart);
#endif

            if (nAdjacency >= 0)
            {
                pFace->AddNeighbor(pIterFace, (nAdjacency / 10));
                pIterFace->AddNeighbor(pFace, (nAdjacency % 10));
            }
        }
    }

#ifdef _TIMING
    m_tAdjLoop += (GetTime() - tMNStart);

    tMNStart = GetTime();
#endif

    // set ID for the face.  This is used for computing faceRemap.
    pFace->SetID(nID);

    // add to the total list of faces
    // push front since this face is likely to be used in upcoming faces
    // and the loop above will work best if the neighbors are found early
    m_faces.push_front(pFace);
#ifdef _TIMING
    m_tPush += GetTime() - tMNStart;
#endif
    return true;
}