//=================================================================
//
// Copyright (c) Microsoft Corporation 1999 - All Rights Reserved.
//
//=================================================================

//-----------------------------------------------------------------------------
//
// _CLIP_TRI_FN_NAME_   Name of the triangle clip function.
// _CLIP_LINE_FN_NAME_  Name of the line clip function.
// _CLIP_COORD_         Coordinates to use in clipping (hx, hy, or hz)
// _CLIP_HW_            Define this if you are clipping against the right, bottom, or back clipping
//                        plane.  (i.e. coord <= hw)
// _CLIP_FLAG_          What to set the clip flag of the new vertex to.
//
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int _CLIP_TRI_FN_NAME_(GRFCLIPVERTEX ** ppcvIn, int cIn, GRFCLIPVERTEX ** ppcvOut,
                       GRFCLIPVERTEX * pcvBuffer, int *pcBuffer)
{
    GRFCLIPVERTEX * pcvPrev;
    GRFCLIPVERTEX * pcvCurr;
    float        dPrev, dCurr;
    int          cOut, cBuffer;
    int          iIn;

    // Start with no verticies out.
    cOut    = 0;
    cBuffer = *pcBuffer;

    // Get the first two vertecies to clip.
    pcvPrev = ppcvIn[cIn - 1];

#ifdef _CLIP_HW_
    dPrev = pcvPrev->hw - pcvPrev->_CLIP_COORD_;
#else
    dPrev = pcvPrev->_CLIP_COORD_;
#endif

    // Loop through all the verticies and clip them to the appropriate clipping coordinate.
    for (iIn = 0; iIn < cIn; iIn++)
    {
        pcvCurr = ppcvIn[iIn]; 

#ifdef _CLIP_HW_
        dCurr = pcvCurr->hw - pcvCurr->_CLIP_COORD_;
#else
        dCurr = pcvCurr->_CLIP_COORD_;
#endif

        if (dPrev < 0.0F)
        {
            // First point outside.
            if (dCurr >= 0.0F)
            {
                // Second point inside.
                ppcvOut[cOut++] = pcvBuffer + cBuffer;
                Interpolate(pcvCurr, pcvPrev, dCurr, dCurr - dPrev, _CLIP_FLAG_, pcvBuffer + cBuffer); 
                cBuffer++;
            }
        }
        else
        {
            // First point inside.
            ppcvOut[cOut++] = pcvPrev;

            if (dCurr <= 0.0F)
            {
                // Second point outside.
                ppcvOut[cOut++] = pcvBuffer + cBuffer;
                Interpolate(pcvPrev, pcvCurr, dPrev, dPrev - dCurr, _CLIP_FLAG_, pcvBuffer + cBuffer); 
                cBuffer++;
            }
        }

        pcvPrev = pcvCurr;
        dPrev   = dCurr;
    }

    *pcBuffer = cBuffer;

    return cOut;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int _CLIP_LINE_FN_NAME_(GRFCLIPVERTEX * pcvVertex1, GRFCLIPVERTEX * pcvVertex2)
{
    GRFCLIPVERTEX   cvNew;
    float           drPlane1, drPlane2;

    // Compute the distance from the clipping plane. 

#ifdef _CLIP_HW_
    drPlane1 = pcvVertex1->hw - pcvVertex1->_CLIP_COORD_;
    drPlane2 = pcvVertex2->hw - pcvVertex2->_CLIP_COORD_;
#else
    drPlane1 = pcvVertex1->_CLIP_COORD_;
    drPlane2 = pcvVertex2->_CLIP_COORD_;
#endif

    // Check first point...
    if (drPlane1 < 0.0F)
    {
        // ... first point outside.  Check second point.
        if (drPlane2 < 0.0F)
            return 0;

        // ... it's inside.  Compute new vertex. 
        Interpolate(pcvVertex2, pcvVertex1, drPlane2, drPlane2 - drPlane1, _CLIP_FLAG_, &cvNew);
        *pcvVertex1 = cvNew;

    }
    else
    {
        // ... first point insdie.  Check second point.
        if (drPlane2 < 0.0F)
        {
            // ... it's outside.  Compute new vertex.
            Interpolate(pcvVertex1, pcvVertex2, drPlane1, drPlane1 - drPlane2, _CLIP_FLAG_, &cvNew); 
            *pcvVertex2 = cvNew;
        }
    }

    return 2;
}

#undef  _CLIP_TRI_FN_NAME_
#undef  _CLIP_LINE_FN_NAME_
#undef  _CLIP_FLAG_
#undef  _CLIP_COORD_
#undef  _CLIP_HW_
