Exemple #1
0
/**
 * @brief makes basewindigs for sides and mins/maxs for the brush
 * @returns false if the brush doesn't enclose a valid volume
 */
static void CreateBrushWindings (bspbrush_t* brush)
{
	int i;

	for (i = 0; i < brush->numsides; i++) {
		side_t* side = &brush->sides[i];
		const plane_t* plane = &mapplanes[side->planenum];
		int j;

		/* evidence that winding_t represents a hessian normal plane */
		winding_t* w = BaseWindingForPlane(plane->normal, plane->dist);

		for (j = 0; j < brush->numsides && w; j++) {
			if (i == j)
				continue;
			/* back side clipaway */
			if (brush->sides[j].planenum == (side->planenum ^ 1))
				continue;
			if (brush->sides[j].bevel)
				continue;
			plane = &mapplanes[brush->sides[j].planenum ^ 1];
			ChopWindingInPlace(&w, plane->normal, plane->dist, 0); /*CLIP_EPSILON); */

			/* fix broken windings that would generate trifans */
			if (!FixWinding(w))
				Verb_Printf(VERB_EXTRA, "removed degenerated edge(s) from winding\n");
		}

		side->winding = w;
	}

	BoundBrush(brush);
}
Exemple #2
0
/*
==================
MakeNodePortal

create the new portal by taking the full plane winding for the cutting plane
and clipping it by all of parents of this node
==================
*/
void MakeNodePortal (node_t *node)
{
    portal_t	*new_portal, *p;
    winding_t	*w;
    vec3_t		normal;
    float		dist;
    int			side;

    w = BaseWindingForNode (node);

    // clip the portal by all the other portals in the node
    for (p = node->portals ; p && w; p = p->next[side])
    {
        if (p->nodes[0] == node)
        {
            side = 0;
            VectorCopy (p->plane.normal, normal);
            dist = p->plane.dist;
        }
        else if (p->nodes[1] == node)
        {
            side = 1;
            VectorSubtract (vec3_origin, p->plane.normal, normal);
            dist = -p->plane.dist;
        }
        else
            Error ("CutNodePortals_r: mislinked portal");

        ChopWindingInPlace (&w, normal, dist, CLIP_EPSILON);
    }

    if (!w)
    {
        return;
    }


    /* ydnar: adding this here to fix degenerate windings */
#if 0
    if( FixWinding( w ) == qfalse )
    {
        c_badportals++;
        FreeWinding( w );
        return;
    }
#endif

    if (WindingIsTiny (w))
    {
        c_tinyportals++;
        FreeWinding (w);
        return;
    }

    new_portal = AllocPortal ();
    new_portal->plane = mapplanes[node->planenum];
    new_portal->onnode = node;
    new_portal->winding = w;
    new_portal->compileFlags = node->compileFlags;
    AddPortalToNodes (new_portal, node->children[0], node->children[1]);
}
Exemple #3
0
qboolean CreateBrushWindings( brush_t *brush ){
	int i, j;
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
	winding_accu_t  *w;
#else
	winding_t   *w;
#endif
	side_t      *side;
	plane_t     *plane;


	/* walk the list of brush sides */
	for ( i = 0; i < brush->numsides; i++ )
	{
		/* get side and plane */
		side = &brush->sides[ i ];
		plane = &mapplanes[ side->planenum ];

		/* make huge winding */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
		w = BaseWindingForPlaneAccu( plane->normal, plane->dist );
#else
		w = BaseWindingForPlane( plane->normal, plane->dist );
#endif

		/* walk the list of brush sides */
		for ( j = 0; j < brush->numsides && w != NULL; j++ )
		{
			if ( i == j ) {
				continue;
			}
			if ( brush->sides[ j ].planenum == ( brush->sides[ i ].planenum ^ 1 ) ) {
				continue;       /* back side clipaway */
			}
			if ( brush->sides[ j ].bevel ) {
				continue;
			}
			plane = &mapplanes[ brush->sides[ j ].planenum ^ 1 ];
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
			ChopWindingInPlaceAccu( &w, plane->normal, plane->dist, 0 );
#else
			ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON );
#endif

			/* ydnar: fix broken windings that would generate trifans */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
			// I think it's better to FixWindingAccu() once after we chop with all planes
			// so that error isn't multiplied.  There is nothing natural about welding
			// the points unless they are the final endpoints.  ChopWindingInPlaceAccu()
			// is able to handle all kinds of degenerate windings.
#else
			FixWinding( w );
#endif
		}

		/* set side winding */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
		if ( w != NULL ) {
			FixWindingAccu( w );
			if ( w->numpoints < 3 ) {
				FreeWindingAccu( w );
				w = NULL;
			}
		}
		side->winding = ( w ? CopyWindingAccuToRegular( w ) : NULL );
		if ( w ) {
			FreeWindingAccu( w );
		}
#else
		side->winding = w;
#endif
	}

	/* find brush bounds */
	return BoundBrush( brush );
}
Exemple #4
0
/* OPTIMIZATION: Union doesn't need to be all-or-nothing. A run of three or more convex
   paths with union ops could be locally resolved and still improve over doing the
   ops one at a time. */
bool SkOpBuilder::resolve(SkPath* result) {
    SkPath original = *result;
    int count = fOps.count();
    bool allUnion = true;
    SkPathPriv::FirstDirection firstDir = SkPathPriv::kUnknown_FirstDirection;
    for (int index = 0; index < count; ++index) {
        SkPath* test = &fPathRefs[index];
        if (kUnion_SkPathOp != fOps[index] || test->isInverseFillType()) {
            allUnion = false;
            break;
        }
        // If all paths are convex, track direction, reversing as needed.
        if (test->isConvex()) {
            SkPathPriv::FirstDirection dir;
            if (!SkPathPriv::CheapComputeFirstDirection(*test, &dir)) {
                allUnion = false;
                break;
            }
            if (firstDir == SkPathPriv::kUnknown_FirstDirection) {
                firstDir = dir;
            } else if (firstDir != dir) {
                SkPath temp;
                temp.reverseAddPath(*test);
                *test = temp;
            }
            continue;
        }
        // If the path is not convex but its bounds do not intersect the others, simplify is enough.
        const SkRect& testBounds = test->getBounds();
        for (int inner = 0; inner < index; ++inner) {
            // OPTIMIZE: check to see if the contour bounds do not intersect other contour bounds?
            if (SkRect::Intersects(fPathRefs[inner].getBounds(), testBounds)) {
                allUnion = false;
                break;
            }
        }
    }
    if (!allUnion) {
        *result = fPathRefs[0];
        for (int index = 1; index < count; ++index) {
            if (!Op(*result, fPathRefs[index], fOps[index], result)) {
                reset();
                *result = original;
                return false;
            }
        }
        reset();
        return true;
    }
    SkPath sum;
    for (int index = 0; index < count; ++index) {
        if (!Simplify(fPathRefs[index], &fPathRefs[index])) {
            reset();
            *result = original;
            return false;
        }
        if (!fPathRefs[index].isEmpty()) {
            // convert the even odd result back to winding form before accumulating it
            if (!FixWinding(&fPathRefs[index])) {
                *result = original;
                return false;
            }
            sum.addPath(fPathRefs[index]);
        }
    }
    reset();
    bool success = Simplify(sum, result);
    if (!success) {
        *result = original;
    }
    return success;
}