Beispiel #1
0
/*
 * @brief Marks all nodes that can be reached by entites
 */
_Bool FloodEntities(tree_t *tree) {
    int32_t i;
    vec3_t origin;
    const char *cl;
    _Bool inside;
    node_t *head_node;

    head_node = tree->head_node;
    Com_Debug("--- FloodEntities ---\n");
    inside = false;
    tree->outside_node.occupied = 0;
    cl = "";

    for (i = 1; i < num_entities; i++) {
        GetVectorForKey(&entities[i], "origin", origin);
        if (VectorCompare(origin, vec3_origin))
            continue;

        cl = ValueForKey(&entities[i], "classname");
        origin[2] += 1; // so objects on floor are ok

        // nudge playerstart around if needed so clipping hulls always
        // have a valid point
        if (!g_strcmp0(cl, "info_player_start")) {
            int32_t x, y;

            for (x = -16; x <= 16; x += 16) {
                for (y = -16; y <= 16; y += 16) {
                    origin[0] += x;
                    origin[1] += y;
                    if (PlaceOccupant(head_node, origin, &entities[i])) {
                        inside = true;
                        goto gotit;
                    }
                    origin[0] -= x;
                    origin[1] -= y;
                }
            }
gotit:
            ;
        } else {
            if (PlaceOccupant(head_node, origin, &entities[i]))
                inside = true;
        }
    }

    if (!inside) {
        Com_Debug("no entities in open -- no filling\n");
    } else if (tree->outside_node.occupied) {
        Com_Debug("entity %s reached from outside -- no filling\n", cl);
    }

    return inside && !tree->outside_node.occupied;
}
Beispiel #2
0
/*
===========
FillOutside

===========
*/
node_t *FillOutside (node_t *node, qboolean leakfile)
{
    int			s;
    vec_t		*v;
    int			i;
    qboolean	inside;
    qboolean	ret;
    vec3_t		origin;
    char		*cl;

    qprintf ("----- FillOutside ----\n");

    if (nofill)
    {
        printf ("skipped\n");
        return node;
    }

    //
    // place markers for all entities so
    // we know if we leak inside
    //
    inside = false;
    for (i=1 ; i<num_entities ; i++)
    {
        GetVectorForKey (&entities[i], "origin", origin);
        if (!VectorCompare(origin, vec3_origin))
        {
            cl = ValueForKey (&entities[i], "classname");
            origin[2] += 1;	// so objects on floor are ok

            // nudge playerstart around if needed so clipping hulls allways
            // have a vlaid point
            if (!strcmp (cl, "info_player_start"))
            {
                int	x, y;

                for (x=-16 ; x<=16 ; x += 16)
                {
                    for (y=-16 ; y<=16 ; y += 16)
                    {
                        origin[0] += x;
                        origin[1] += y;
                        if (PlaceOccupant (i, origin, node))
                        {
                            inside = true;
                            goto gotit;
                        }
                        origin[0] -= x;
                        origin[1] -= y;
                    }
                }
gotit:
                ;
            }
            else
            {
                if (PlaceOccupant (i, origin, node))
                    inside = true;
            }
        }
    }

    if (!inside)
    {
        printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum);
        return node;
    }

    s = !(outside_node.portals->nodes[1] == &outside_node);

// first check to see if an occupied leaf is hit
    outleafs = 0;
    valid++;

    prevleaknode = NULL;

    if (leakfile)
    {
        pointfile = fopen (pointfilename, "w");
        if (!pointfile)
            Error ("Couldn't open %s\n", pointfilename);
        StripExtension (pointfilename);
        strcat (pointfilename, ".lin");
        linefile = fopen (pointfilename, "w");
        if (!linefile)
            Error ("Couldn't open %s\n", pointfilename);
    }

    ret = RecursiveFillOutside (outside_node.portals->nodes[s], false);

    if (leakfile)
    {
        fclose (pointfile);
        fclose (linefile);
    }

    if (ret)
    {
        printf("LEAK LEAK LEAK\n");
        GetVectorForKey (&entities[hit_occupied], "origin", origin);
        qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
        qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n"
                 , origin[0], origin[1], origin[2]);
        qprintf ("no filling performed\n");
        qprintf ("point file and line file generated\n");
        qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
        if (leakonly)
            Error ("Stopped by leak.");
        return node;
    }

// now go back and fill things in
    valid++;
    RecursiveFillOutside (outside_node.portals->nodes[s], true);

// remove faces and nodes from filled in leafs
    c_falsenodes = 0;
    c_free_faces = 0;
    c_keep_faces = 0;
    node = ClearOutFaces_r (node);

    qprintf ("%5i outleafs\n", outleafs);
    qprintf ("%5i freed faces\n", c_free_faces);
    qprintf ("%5i keep faces\n", c_keep_faces);
    qprintf ("%5i falsenodes\n", c_falsenodes);

// save portal file for vis tracing
    if (leakfile)
        WritePortalfile (node);

    return node;
}
Beispiel #3
0
/*
===========
FillOutside

===========
*/
qboolean FillOutside (node_t *node)
{
	int			s;
	vec_t		*v;
	int			i;
	qboolean	inside;
	
	qprintf ("----- FillOutside ----\n");

	if (nofill)
	{
		printf ("skipped\n");
		return false;
	}
		
	inside = false;
	for (i=1 ; i<num_entities ; i++)
	{
		if (!VectorCompare(entities[i].origin, vec3_origin))
		{
			if (PlaceOccupant (i, entities[i].origin, node))
				inside = true;
		}
	}

	if (!inside)
	{
		printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum);
		return false;
	}

	s = !(outside_node.portals->nodes[1] == &outside_node);

// first check to see if an occupied leaf is hit
	outleafs = 0;
	valid++;

	prevleaknode = NULL;
	
	if (!hullnum)
	{
		leakfile = fopen (pointfilename, "w");
		if (!leakfile)
			Error ("Couldn't open %s\n", pointfilename);
	}

	if (RecursiveFillOutside (outside_node.portals->nodes[s], false))
	{
		v = entities[hit_occupied].origin;
		qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
		qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n"
		, v[0], v[1], v[2]);
		qprintf ("no filling performed\n");
		if (!hullnum)
			fclose (leakfile);
		qprintf ("leak file written to %s\n", pointfilename);			
		qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
		return false;
	}
	if (!hullnum)
		fclose (leakfile);

// now go back and fill things in
	valid++;
	RecursiveFillOutside (outside_node.portals->nodes[s], true);

// remove faces from filled in leafs	
	ClearOutFaces (node);
	
	qprintf ("%4i outleafs\n", outleafs);
	return true;
}
Beispiel #4
0
//===========================================================================
// Marks all nodes that can be reached by entites
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
qboolean FloodEntities(tree_t *tree)
{
	int i;
	int x, y;
	vec3_t origin;
	char *cl;
	qboolean inside;
	node_t *headnode;

	headnode = tree->headnode;
	Log_Print("------ FloodEntities -------\n");
	inside = false;
	tree->outside_node.occupied = 0;

	//start at entity 1 not the world ( = 0)
	for(i = 1; i < num_entities; i++)
	{
		GetVectorForKey(&entities[i], "origin", origin);

		if(VectorCompare(origin, vec3_origin))
		{
			continue;
		}

		cl = ValueForKey(&entities[i], "classname");
		origin[2] += 1; //so objects on floor are ok

//		Log_Print("flooding from entity %d: %s\n", i, cl);
		//nudge playerstart around if needed so clipping hulls allways
		//have a valid point
		if(!strcmp(cl, "info_player_start"))
		{
			for(x = -16; x <= 16; x += 16)
			{
				for(y = -16; y <= 16; y += 16)
				{
					origin[0] += x;
					origin[1] += y;

					if(PlaceOccupant(headnode, origin, &entities[i]))
					{
						inside = true;
						x = 999; //stop for this info_player_start
						break;
					} //end if

					origin[0] -= x;
					origin[1] -= y;
				} //end for
			} //end for
		} //end if
		else
		{
			if(PlaceOccupant(headnode, origin, &entities[i]))
			{
				inside = true;
			} //end if
		} //end else
	} //end for

	if(!inside)
	{
		Log_Print("WARNING: no entities inside\n");
	} //end if
	else if(tree->outside_node.occupied)
	{
		Log_Print("WARNING: entity reached from outside\n");
	} //end else if

	return (qboolean)(inside && !tree->outside_node.occupied);
} //end of the function FloodEntities
/*
=============
FloodEntities

Marks all nodes that can be reached by entites
=============
*/
bool FloodEntities( tree_t *tree ) {
	int		i;
	idVec3	origin;
	const char	*cl;
	bool	inside;
	node_t *headnode;
	headnode = tree->headnode;
	common->Printf( "--- FloodEntities ---\n" );
	inside = false;
	tree->outside_node.occupied = 0;
	c_floodedleafs = 0;
	bool errorShown = false;
	for( i = 1 ; i < dmapGlobals.num_entities ; i++ ) {
		idMapEntity	*mapEnt;
		mapEnt = dmapGlobals.uEntities[i].mapEntity;
		if( !mapEnt->epairs.GetVector( "origin", "", origin ) ) {
			continue;
		}
		// any entity can have "noFlood" set to skip it
		if( mapEnt->epairs.GetString( "noFlood", "", &cl ) ) {
			continue;
		}
		mapEnt->epairs.GetString( "classname", "", &cl );
		if( !strcmp( cl, "light" ) ) {
			const char	*v;
			// don't place lights that have a light_start field, because they can still
			// be valid if their origin is outside the world
			mapEnt->epairs.GetString( "light_start", "", &v );
			if( v[0] ) {
				continue;
			}
			// don't place fog lights, because they often
			// have origins outside the light
			mapEnt->epairs.GetString( "texture", "", &v );
			if( v[0] ) {
				const idMaterial *mat = declManager->FindMaterial( v );
				if( mat->IsFogLight() ) {
					continue;
				}
			}
		}
		if( PlaceOccupant( headnode, origin, &dmapGlobals.uEntities[i] ) ) {
			inside = true;
		}
		if( tree->outside_node.occupied && !errorShown ) {
			errorShown = true;
			common->Printf( "Leak on entity # %d\n", i );
			const char *p;
			mapEnt->epairs.GetString( "classname", "", &p );
			common->Printf( "Entity classname was: %s\n", p );
			mapEnt->epairs.GetString( "name", "", &p );
			common->Printf( "Entity name was: %s\n", p );
			idVec3 origin;
			if( mapEnt->epairs.GetVector( "origin", "", origin ) ) {
				common->Printf( "Entity origin is: %f %f %f\n\n\n", origin.x, origin.y, origin.z );
			}
		}
	}
	common->Printf( "%5i flooded leafs\n", c_floodedleafs );
	if( !inside ) {
		common->Printf( "no entities in open -- no filling\n" );
	} else if( tree->outside_node.occupied ) {
		common->Printf( "entity reached from outside -- no filling\n" );
	}
	return ( bool )( inside && !tree->outside_node.occupied );
}
Beispiel #6
0
qboolean FloodEntities( tree_t *tree )
{
    int			i, s;
    vec3_t		origin, offset, scale, angles;
    qboolean	r, inside, tripped, skybox;
    node_t		*headnode;
    entity_t	*e;
    const char	*value;


    headnode = tree->headnode;
    Sys_FPrintf( SYS_VRB,"--- FloodEntities ---\n" );
    inside = qfalse;
    tree->outside_node.occupied = 0;

    tripped = qfalse;
    c_floodedleafs = 0;
    for( i = 1; i < numEntities; i++ )
    {
        /* get entity */
        e = &entities[ i ];

        /* get origin */
        GetVectorForKey( e, "origin", origin );
        if( VectorCompare( origin, vec3_origin ) )
            continue;

        /* handle skybox entities */
        value = ValueForKey( e, "classname" );
        if( !Q_stricmp( value, "_skybox" ) )
        {
            skybox = qtrue;
            skyboxPresent = qtrue;

            /* invert origin */
            VectorScale( origin, -1.0f, offset );

            /* get scale */
            VectorSet( scale, 64.0f, 64.0f, 64.0f );
            value = ValueForKey( e, "_scale" );
            if( value[ 0 ] != '\0' )
            {
                s = sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
                if( s == 1 )
                {
                    scale[ 1 ] = scale[ 0 ];
                    scale[ 2 ] = scale[ 0 ];
                }
            }

            /* get "angle" (yaw) or "angles" (pitch yaw roll) */
            VectorClear( angles );
            angles[ 2 ] = FloatForKey( e, "angle" );
            value = ValueForKey( e, "angles" );
            if( value[ 0 ] != '\0' )
                sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );

            /* set transform matrix (thanks spog) */
            m4x4_identity( skyboxTransform );
            m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin );
        }
        else
            skybox = qfalse;

        /* nudge off floor */
        origin[ 2 ] += 1;

        /* debugging code */
        //%	if( i == 1 )
        //%		origin[ 2 ] += 4096;

        /* find leaf */
        r = PlaceOccupant( headnode, origin, e, skybox );
        if( r )
            inside = qtrue;
        if( (!r || tree->outside_node.occupied) && !tripped )
        {
            xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse );
            tripped = qtrue;
        }
    }

    Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );

    if( !inside )
        Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" );
    else if( tree->outside_node.occupied )
        Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" );

    return (qboolean) (inside && !tree->outside_node.occupied);
}
Beispiel #7
0
/*
===========
FillOutside

===========
*/
qboolean FillOutside (tree_t *tree, int hullnum)
{
	int			i;
	int			s;
	qboolean	inside;
	vec3_t		origin;

	qprintf ("----- FillOutside ----\n");

	if (nofill)
	{
		printf ("skipped\n");
		return false;
	}

	inside = false;
	for (i=1 ; i<num_entities ; i++)
	{
		GetVectorForKey (&entities[i], "origin", origin);

		if (DotProduct (origin, origin) >= 0.1)
		{
			if (PlaceOccupant (i, origin, tree->headnode))
				inside = true;
		}
	}

	if (!inside)
	{
		printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum);
		return false;
	}

	s = !(outside_node.portals->nodes[1] == &outside_node);

// first check to see if an occupied leaf is hit
	outleafs = 0;
	valid++;

	prevleaknode = NULL;

	if (RecursiveFillOutside (outside_node.portals->nodes[s], hullnum, false))
	{
		if (leakfile)
			fclose(leakfile);
		leakfile = NULL;
		if (!hullnum)
		{
			GetVectorForKey (&entities[hit_occupied], "origin", origin);

			qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
			qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n", origin[0], origin[1], origin[2]);
			qprintf ("no filling performed\n");
			qprintf ("leak file written to %s\n", filename_pts);
			qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
		}

		// remove faces from filled in leafs
		ClearOutFaces (tree->headnode);
		return false;
	}

	// now go back and fill things in
	valid++;
	RecursiveFillOutside (outside_node.portals->nodes[s], hullnum, true);

	// remove faces from filled in leafs
	ClearOutFaces (tree->headnode);

	qprintf ("%4i outleafs\n", outleafs);
	return true;
}