示例#1
0
void Winding::Divide(const dplane_t& split, Winding** front, Winding** back)
{
    vec_t           dists[MAX_POINTS_ON_WINDING];
    int             sides[MAX_POINTS_ON_WINDING];
    int             counts[3];
    vec_t           dot;
    int             i, j;
    int             maxpts;

    counts[0] = counts[1] = counts[2] = 0;

    // determine sides for each point
    for (i = 0; i < m_NumPoints; i++)
    {
        dot = DotProduct(m_Points[i], split.normal);
        dot -= split.dist;
        dists[i] = dot;
        if (dot > ON_EPSILON)
        {
            sides[i] = SIDE_FRONT;
        }
        else if (dot < -ON_EPSILON)
        {
            sides[i] = SIDE_BACK;
        }
        else
        {
            sides[i] = SIDE_ON;
        }
        counts[sides[i]]++;
    }
    sides[i] = sides[0];
    dists[i] = dists[0];

    *front = *back = NULL;

    if (!counts[0])
    {
        *back = this;   // Makes this function non-const
        return;
    }
    if (!counts[1])
    {
        *front = this;  // Makes this function non-const
        return;
    }

    maxpts = m_NumPoints + 4;                            // can't use counts[0]+2 because
    // of fp grouping errors

    Winding* f = new Winding(maxpts);
    Winding* b = new Winding(maxpts);

    *front = f;
    *back = b;

    f->m_NumPoints = 0;
    b->m_NumPoints = 0;

    for (i = 0; i < m_NumPoints; i++)
    {
        vec_t* p1 = m_Points[i];

        if (sides[i] == SIDE_ON)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            f->m_NumPoints++;
            b->m_NumPoints++;
            continue;
        }
        else if (sides[i] == SIDE_FRONT)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            f->m_NumPoints++;
        }
        else if (sides[i] == SIDE_BACK)
        {
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            b->m_NumPoints++;
        }

        if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
        {
            continue;
        }

        // generate a split point
        vec3_t mid;
        unsigned int tmp = i + 1;
        if (tmp >= m_NumPoints)
        {
            tmp = 0;
        }
        vec_t* p2 = m_Points[tmp];
        dot = dists[i] / (dists[i] - dists[i + 1]);
        for (j = 0; j < 3; j++)
        {   // avoid round off error when possible
            if (split.normal[j] < 1.0 - NORMAL_EPSILON)
            {
                if (split.normal[j] > -1.0 + NORMAL_EPSILON)
                {
                    mid[j] = p1[j] + dot * (p2[j] - p1[j]);
                }
                else
                {
                    mid[j] = -split.dist;
                }
            }
            else
            {
                mid[j] = split.dist;
            }
        }

        VectorCopy(mid, f->m_Points[f->m_NumPoints]);
        VectorCopy(mid, b->m_Points[b->m_NumPoints]);
        f->m_NumPoints++;
        b->m_NumPoints++;
    }

    if (f->m_NumPoints > maxpts || b->m_NumPoints > maxpts)
    {
        Error("Winding::Divide : points exceeded estimate");
    }

    f->RemoveColinearPoints();
    b->RemoveColinearPoints();
}
示例#2
0
void            Winding::Clip(const vec3_t normal, const vec_t dist, Winding** front, Winding** back)
{
    vec_t           dists[MAX_POINTS_ON_WINDING + 4];
    int             sides[MAX_POINTS_ON_WINDING + 4];
    int             counts[3];
    vec_t           dot;
    unsigned int    i, j;
    unsigned int    maxpts;

    counts[0] = counts[1] = counts[2] = 0;

    // determine sides for each point
    for (i = 0; i < m_NumPoints; i++)
    {
        dot = DotProduct(m_Points[i], normal);
        dot -= dist;
        dists[i] = dot;
        if (dot > ON_EPSILON)
        {
            sides[i] = SIDE_FRONT;
        }
        else if (dot < -ON_EPSILON)
        {
            sides[i] = SIDE_BACK;
        }
        else
        {
            sides[i] = SIDE_ON;
        }
        counts[sides[i]]++;
    }
    sides[i] = sides[0];
    dists[i] = dists[0];

    if (!counts[0])
    {
        *front = NULL;
        *back = new Winding(*this);
        return;
    }
    if (!counts[1])
    {
        *front = new Winding(*this);
        *back = NULL;
        return;
    }

    maxpts = m_NumPoints + 4;                            // can't use counts[0]+2 because
    // of fp grouping errors

    Winding* f = new Winding(maxpts);
    Winding* b = new Winding(maxpts);

    *front = f;
    *back = b;

    f->m_NumPoints = 0;
    b->m_NumPoints = 0;

    for (i = 0; i < m_NumPoints; i++)
    {
        vec_t* p1 = m_Points[i];

        if (sides[i] == SIDE_ON)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            f->m_NumPoints++;
            b->m_NumPoints++;
            continue;
        }
        else if (sides[i] == SIDE_FRONT)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            f->m_NumPoints++;
        }
        else if (sides[i] == SIDE_BACK)
        {
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            b->m_NumPoints++;
        }

        if ((sides[i + 1] == SIDE_ON) | (sides[i + 1] == sides[i]))  // | instead of || for branch optimization
        {
            continue;
        }

        // generate a split point
        vec3_t mid;
        unsigned int tmp = i + 1;
        if (tmp >= m_NumPoints)
        {
            tmp = 0;
        }
        vec_t* p2 = m_Points[tmp];
        dot = dists[i] / (dists[i] - dists[i + 1]);
#if 0
        for (j = 0; j < 3; j++)
        {   // avoid round off error when possible
            if (normal[j] < 1.0 - NORMAL_EPSILON)
            {
                if (normal[j] > -1.0 + NORMAL_EPSILON)
                {
                    mid[j] = p1[j] + dot * (p2[j] - p1[j]);
                }
                else
                {
                    mid[j] = -dist;
                }
            }
            else
            {
                mid[j] = dist;
            }
        }
#else
        for (j = 0; j < 3; j++)
        {   // avoid round off error when possible
            if (normal[j] == 1)
                mid[j] = dist;
            else if (normal[j] == -1)
                mid[j] = -dist;
            else
                mid[j] = p1[j] + dot * (p2[j] - p1[j]);
        }
#endif

        VectorCopy(mid, f->m_Points[f->m_NumPoints]);
        VectorCopy(mid, b->m_Points[b->m_NumPoints]);
        f->m_NumPoints++;
        b->m_NumPoints++;
    }

    if ((f->m_NumPoints > maxpts) | (b->m_NumPoints > maxpts)) // | instead of || for branch optimization
    {
        Error("Winding::Clip : points exceeded estimate");
    }
    if ((f->m_NumPoints > MAX_POINTS_ON_WINDING) | (b->m_NumPoints > MAX_POINTS_ON_WINDING)) // | instead of || for branch optimization
    {
        Error("Winding::Clip : MAX_POINTS_ON_WINDING");
    }
    f->RemoveColinearPoints();
    b->RemoveColinearPoints();
}