Esempio n. 1
0
File: facebsp.c Progetto: otty/cake3
/*
================
BuildFaceTree_r
================
*/
void BuildFaceTree_r(node_t * node, bspFace_t * list)
{
	bspFace_t      *split;
	bspFace_t      *next;
	int             side;
	plane_t        *plane;
	bspFace_t      *newFace;
	bspFace_t      *childLists[2];
	winding_t      *frontWinding, *backWinding;
	int             i;
	int             splitPlaneNum;
	int             hintSplit;

	i = CountFaceList(list);

	SelectSplitPlaneNum(node, list, &splitPlaneNum, &hintSplit);

	// if we don't have any more faces, this is a node
	if(splitPlaneNum == -1)
	{
		node->planenum = PLANENUM_LEAF;
		c_faceLeafs++;
		return;
	}

	// partition the list
	node->planenum = splitPlaneNum;
	node->hint = hintSplit;
	plane = &mapPlanes[splitPlaneNum];
	childLists[0] = NULL;
	childLists[1] = NULL;
	for(split = list; split; split = next)
	{
		next = split->next;

		if(split->planenum == node->planenum)
		{
			FreeBspFace(split);
			continue;
		}

		side = WindingOnPlaneSide(split->w, plane->normal, plane->dist);

		if(side == SIDE_CROSS)
		{
			ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding);
			if(frontWinding)
			{
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->hint = split->hint;
				childLists[0] = newFace;
			}
			if(backWinding)
			{
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->hint = split->hint;
				childLists[1] = newFace;
			}
			FreeBspFace(split);
		}
		else if(side == SIDE_FRONT)
		{
			split->next = childLists[0];
			childLists[0] = split;
		}
		else if(side == SIDE_BACK)
		{
			split->next = childLists[1];
			childLists[1] = split;
		}
	}


	// recursively process children
	for(i = 0; i < 2; i++)
	{
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		VectorCopy(node->mins, node->children[i]->mins);
		VectorCopy(node->maxs, node->children[i]->maxs);
	}

	for(i = 0; i < 3; i++)
	{
		if(plane->normal[i] == 1)
		{
			node->children[0]->mins[i] = plane->dist;
			node->children[1]->maxs[i] = plane->dist;
			break;
		}
	}

	for(i = 0; i < 2; i++)
	{
		BuildFaceTree_r(node->children[i], childLists[i]);
	}
}
Esempio n. 2
0
/*
================
BuildFaceTree_r
================
*/
void	BuildFaceTree_r( node_t *node, bspface_t *list ) {
	bspface_t	*split;
	bspface_t	*next;
	int			side;
	bspface_t	*newFace;
	bspface_t	*childLists[2];
	idWinding	*frontWinding, *backWinding;
	int			i;
	int			splitPlaneNum;

	splitPlaneNum = SelectSplitPlaneNum( node, list );
	// if we don't have any more faces, this is a node
	if ( splitPlaneNum == -1 ) {
		node->planenum = PLANENUM_LEAF;
		c_faceLeafs++;
		return;
	}

	// partition the list
	node->planenum = splitPlaneNum;
	idPlane &plane = dmapGlobals.mapPlanes[ splitPlaneNum ];
	childLists[0] = NULL;
	childLists[1] = NULL;
	for ( split = list ; split ; split = next ) {
		next = split->next;

		if ( split->planenum == node->planenum ) {
			FreeBspFace( split );
			continue;
		}

		side = split->w->PlaneSide( plane );

		if ( side == SIDE_CROSS ) {
			split->w->Split( plane, CLIP_EPSILON * 2, &frontWinding, &backWinding );
			if ( frontWinding ) {
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				childLists[0] = newFace;
			}
			if ( backWinding ) {
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				childLists[1] = newFace;
			}
			FreeBspFace( split );
		} else if ( side == SIDE_FRONT ) {
			split->next = childLists[0];
			childLists[0] = split;
		} else if ( side == SIDE_BACK ) {
			split->next = childLists[1];
			childLists[1] = split;
		}
	}


	// recursively process children
	for ( i = 0 ; i < 2 ; i++ ) {
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		node->children[i]->bounds = node->bounds;
	}

	// split the bounds if we have a nice axial plane
	for ( i = 0 ; i < 3 ; i++ ) {
		if ( idMath::Fabs( plane[i] - 1.0 ) < 0.001 ) {
			node->children[0]->bounds[0][i] = plane.Dist();
			node->children[1]->bounds[1][i] = plane.Dist();
			break;
		}
	}

	for ( i = 0 ; i < 2 ; i++ ) {
		BuildFaceTree_r ( node->children[i], childLists[i]);
	}
}
Esempio n. 3
0
void BuildFaceTree_r( node_t *node, face_t *list )
{
	face_t		*split;
	face_t		*next;
	int			side;
	plane_t		*plane;
	face_t		*newFace;
	face_t		*childLists[2];
	winding_t	*frontWinding, *backWinding;
	int			i;
	int			splitPlaneNum, compileFlags;
	
	
	/* count faces left */
	i = CountFaceList( list );
	
	/* select the best split plane */
	SelectSplitPlaneNum( node, list, &splitPlaneNum, &compileFlags );
	
	/* if we don't have any more faces, this is a node */
	if ( splitPlaneNum == -1 )
	{
		node->planenum = PLANENUM_LEAF;
		c_faceLeafs++;
		return;
	}
	
	/* partition the list */
	node->planenum = splitPlaneNum;
	node->compileFlags = compileFlags;
	plane = &mapplanes[ splitPlaneNum ];
	childLists[0] = NULL;
	childLists[1] = NULL;
	for( split = list; split; split = next )
	{
		/* set next */
		next = split->next;
		
		/* don't split by identical plane */
		if( split->planenum == node->planenum )
		{
			FreeBspFace( split );
			continue;
		}
		
		/* determine which side the face falls on */
		side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
		
		/* switch on side */
		if( side == SIDE_CROSS )
		{
			ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
				&frontWinding, &backWinding );
			if( frontWinding ) {
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[0] = newFace;
			}
			if( backWinding ) {
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[1] = newFace;
			}
			FreeBspFace( split );
		} else if ( side == SIDE_FRONT ) {
			split->next = childLists[0];
			childLists[0] = split;
		} else if ( side == SIDE_BACK ) {
			split->next = childLists[1];
			childLists[1] = split;
		}
	}


	// recursively process children
	for ( i = 0 ; i < 2 ; i++ ) {
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		VectorCopy( node->mins, node->children[i]->mins );
		VectorCopy( node->maxs, node->children[i]->maxs );
	}

	for ( i = 0 ; i < 3 ; i++ ) {
		if ( plane->normal[i] == 1 ) {
			node->children[0]->mins[i] = plane->dist;
			node->children[1]->maxs[i] = plane->dist;
			break;
		}
	}

	for ( i = 0 ; i < 2 ; i++ ) {
		BuildFaceTree_r ( node->children[i], childLists[i]);
	}
}
Esempio n. 4
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
tree_t *ProcessWorldBrushes(int brush_start, int brush_end)
{
	bspbrush_t *brushes;
	tree_t *tree;
	node_t *node;
	vec3_t mins, maxs;

	//take the whole world
	mins[0] = map_mins[0] - 8;
	mins[1] = map_mins[1] - 8;
	mins[2] = map_mins[2] - 8;

	maxs[0] = map_maxs[0] + 8;
	maxs[1] = map_maxs[1] + 8;
	maxs[2] = map_maxs[2] + 8;

	//reset the brush bsp
	ResetBrushBSP();

	// the makelist and chopbrushes could be cached between the passes...

	//create a list with brushes that are within the given mins/maxs
	//some brushes will be cut and only the part that falls within the
	//mins/maxs will be in the bush list
	brushes = MakeBspBrushList(brush_start, brush_end, mins, maxs);
	//

	if (!brushes)
	{
		node = AllocNode ();
		node->planenum = PLANENUM_LEAF;
		node->contents = CONTENTS_SOLID;

		tree = Tree_Alloc();
		tree->headnode = node;
		VectorCopy(mins, tree->mins);
		VectorCopy(maxs, tree->maxs);
	} //end if
	else
	{
		//Carves any intersecting solid brushes into the minimum number
		//of non-intersecting brushes. 
		if (!nocsg)
		{
			brushes = ChopBrushes(brushes);
			/*
			if (create_aas)
			{
				brushes = MergeBrushes(brushes);
			} //end if*/
		} //end if
		//if the conversion is cancelled
		if (cancelconversion)
		{
			FreeBrushList(brushes);
			return NULL;
		} //end if
		//create the actual bsp tree
		tree = BrushBSP(brushes, mins, maxs);
	} //end else
	//return the tree
	return tree;
} //end of the function ProcessWorldBrushes
Esempio n. 5
0
File: bsp.c Progetto: otty/cake3
/*
============
ProcessSubModel
============
*/
void ProcessSubModel(int entityNum)
{
	entity_t       *e;
	tree_t         *tree;
	bspBrush_t     *b, *bc;
	node_t         *node;

	e = &entities[entityNum];
	e->firstDrawSurf = numMapDrawSurfs;

	BeginModel(e);

	PatchMapDrawSurfs(e);

	// just put all the brushes in an empty leaf
	// FIXME: patches?
	node = AllocNode();
	node->planenum = PLANENUM_LEAF;
	for(b = e->brushes; b; b = b->next)
	{
		bc = CopyBrush(b);
		bc->next = node->brushlist;
		node->brushlist = bc;
	}

	tree = AllocTree();
	tree->headnode = node;

	ClipSidesIntoTree(e, tree);

	// create drawsurfs for triangle models
	AddTriangleModel(e, qfalse);

	// subdivide each drawsurf as required by shader tesselation or fog
	if(!nosubdivide)
	{
		SubdivideDrawSurfs(e, tree);
	}

	// merge together all common shaders on the same plane and remove 
	// all colinear points, so extra tjunctions won't be generated
	if(!nomerge)
	{
		MergeSides(e, tree);	// !@# testing
	}

	// add in any vertexes required to fix tjunctions
	if(!notjunc)
	{
		FixTJunctions(e);
	}

	// allocate lightmaps for faces and patches
	AllocateLightmaps(e);

	// add references to the final drawsurfs in the apropriate clusters
	FilterDrawsurfsIntoTree(e, tree);

	EndModel(e, node);

	FreeTree(tree);
}
Esempio n. 6
0
static orl_return ProcSymbol( orl_symbol_handle symhdl )
/******************************************************/
{
    orl_symbol_type     type;
    char                *name;
    orl_symbol_value    value;
    orl_sec_handle      sechdl;
    symbol              *sym;
    size_t              namelen;
    sym_flags           symop;
    extnode             *newnode;
    segnode             *snode;
    bool                isweak;
    orl_symbol_handle   assocsymhdl;
    symbol              *assocsym;
    orl_symbol_binding  binding;

    sechdl = ORLSymbolGetSecHandle( symhdl );
    snode = FindSegNode( sechdl );
    type = ORLSymbolGetType( symhdl );
    name = ORLSymbolGetName( symhdl );
    if( type & ORL_SYM_TYPE_FILE ) {
        if( !(CurrMod->modinfo & MOD_GOT_NAME) ) {
            CurrMod->modinfo |= MOD_GOT_NAME;
            _LnkFree( CurrMod->name );
            CurrMod->name = AddStringStringTable( &PermStrings, name );
        }
        return( ORL_OKAY );
    }
    if( type & ORL_SYM_TYPE_DEBUG )
        return( ORL_OKAY );
    if( type & (ORL_SYM_TYPE_OBJECT|ORL_SYM_TYPE_FUNCTION) ||
        (type & (ORL_SYM_TYPE_NOTYPE|ORL_SYM_TYPE_UNDEFINED) &&
         name != NULL)) {
        namelen = strlen( name );
        if( namelen == 0 ) {
            BadObject();
        }
        if( CurrMod->modinfo & MOD_IMPORT_LIB ) {
            ImpProcSymbol( snode, type, name, namelen );
            return( ORL_OKAY );
        }
        newnode = AllocNode( ExtNodes );
        newnode->handle = symhdl;
        binding = ORLSymbolGetBinding( symhdl );
        symop = ST_CREATE;
        if( binding == ORL_SYM_BINDING_LOCAL ) {
            symop |= ST_STATIC | ST_NONUNIQUE;
        }
        if( type & ORL_SYM_TYPE_UNDEFINED && binding != ORL_SYM_BINDING_ALIAS ){
            symop |= ST_REFERENCE;
        } else {
            symop |= ST_NOALIAS;
        }
        sym = SymOp( symop, name, namelen );
        CheckIfTocSym( sym );
        if( type & ORL_SYM_TYPE_COMMON ) {
            value = ORLSymbolGetValue( symhdl );
            sym = MakeCommunalSym( sym, value, FALSE, TRUE );
        } else if( type & ORL_SYM_TYPE_UNDEFINED ) {
            DefineReference( sym );
            isweak = FALSE;
            switch( binding ) {
            case ORL_SYM_BINDING_WEAK:
                isweak = TRUE;
            case ORL_SYM_BINDING_ALIAS:
            case ORL_SYM_BINDING_LAZY:
                assocsymhdl = ORLSymbolGetAssociated( symhdl );
                name = ORLSymbolGetName( assocsymhdl );
                namelen = strlen(name);
                if( binding == ORL_SYM_BINDING_ALIAS ) {
                    MakeSymAlias( sym->name, strlen(sym->name), name, namelen );
                } else {
                    assocsym = SymOp( ST_CREATE | ST_REFERENCE, name, namelen );
                    DefineLazyExtdef( sym, assocsym, isweak );
                    newnode->isweak = TRUE;
                }
            }
        } else {
            newnode->isdefd = TRUE;
            value = ORLSymbolGetValue( symhdl );
            if( type & ORL_SYM_TYPE_COMMON && type & ORL_SYM_TYPE_OBJECT
                        && sechdl == NULL) {
                sym = MakeCommunalSym( sym, value, FALSE, TRUE );
            } else if( snode != NULL && snode->entry != NULL
                                     && snode->entry->iscdat ) {
                DefineComdatSym( snode, sym, value );
            } else {
                sym->info |= SYM_DEFINED;
                DefineSymbol( sym, snode, value, 0 );
            }
        }
        newnode->entry = sym;
    } else if( type & ORL_SYM_TYPE_SECTION && type & ORL_SYM_CDAT_MASK
                            && snode != NULL && !(snode->info & SEG_DEAD) ) {
        snode->entry->select = (type & ORL_SYM_CDAT_MASK) >> ORL_SYM_CDAT_SHIFT;
    }
Esempio n. 7
0
void BVHTree::BuildNode(BVHNode *node,
			const objPtr_t *objPtrs,
			const Aabb *objAabbs,
			std::vector<objPtr_t> &activeObjIdx)
{
	const int numTris = activeObjIdx.size();
	if (numTris <= 0) Error("BuildNode called with no elements in activeObjIndex.");

	if (numTris == 1) {
		MakeLeaf(node, objPtrs, activeObjIdx);
		return;
	}

	std::vector<int> splitSides(numTris);

	Aabb aabb;
	aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
	aabb.max = vector3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);

	for (int i=0; i<numTris; i++) {
		int idx = activeObjIdx[i];
		aabb.Update(objAabbs[idx].min);
		aabb.Update(objAabbs[idx].max);
	}
	node->numTris = numTris;
	node->aabb = aabb;

	Aabb splitBox = aabb;
	double splitPos;
	int splitAxis;
	int s1count, s2count;
	int attempt = 0;

	for (;;) {
		splitAxis = 0;

		vector3d boxSize = splitBox.max - splitBox.min;

		if (boxSize[1] > boxSize[0]) splitAxis = 1;
		if ((boxSize[2] > boxSize[1]) && (boxSize[2] > boxSize[0])) splitAxis = 2;

		// split pos in middle of splitBox
		splitPos = 0.5f * (splitBox.min[splitAxis] + splitBox.max[splitAxis]);
		s1count = 0, s2count = 0;

		for (int i=0; i<numTris; i++) {
			int idx = activeObjIdx[i];
			double mid = 0.5 * (objAabbs[idx].min[splitAxis] + objAabbs[idx].max[splitAxis]);
			if (mid < splitPos) {
				splitSides[i] = 0;
				s1count++;
			} else {
				splitSides[i] = 1;
				s2count++;
			}
		}

		if (s1count == numTris) {
			if (attempt < MAX_SPLITPOS_RETRIES) {
				// try splitting at average point
				splitBox.max[splitAxis] = splitPos;
				attempt++;
				continue;
			} else {
				MakeLeaf(node, objPtrs, activeObjIdx);
				return;
			}
		} else if (s2count == numTris) {
			if (attempt < MAX_SPLITPOS_RETRIES) {
				// try splitting at average point
				splitBox.min[splitAxis] = splitPos;
				attempt++;
				continue;
			} else {
				MakeLeaf(node, objPtrs, activeObjIdx);
				return;
			}
		}
		break;
	}

	std::vector<int> side[2];

	for (int i=0; i<numTris; i++) {
		side[splitSides[i]].push_back(activeObjIdx[i]);
	}

	// recurse!
	node->triIndicesStart = 0;
	node->kids[0] = AllocNode();
	node->kids[1] = AllocNode();

	BuildNode(node->kids[0], objPtrs, objAabbs, side[0]);
	BuildNode(node->kids[1], objPtrs, objAabbs, side[1]);
}
Esempio n. 8
0
void BuildFaceTree_r(node_t * node, face_t * list)
{
	face_t         *split;
	face_t         *next;
	int             side;
	plane_t        *plane;
	face_t         *newFace;
	face_t         *childLists[2];
	winding_t      *frontWinding, *backWinding;
	int             i;
	int             splitPlaneNum, compileFlags;
	qboolean        isstruct = qfalse;
	int             splits, front, back;


	/* count faces left */
	i = CountFaceList(list);

#if defined(DEBUG_SPLITS)
	Sys_FPrintf(SYS_VRB, "faces left = %d\n", i);
#endif

	/* select the best split plane */
	SelectSplitPlaneNum(node, list, &splitPlaneNum, &compileFlags);

	/* if we don't have any more faces, this is a leaf */
	if(splitPlaneNum == -1)
	{
		node->planenum = PLANENUM_LEAF;
		node->has_structural_children = qfalse;
		c_faceLeafs++;
		return;
	}

	/* partition the list */
	node->planenum = splitPlaneNum;
	node->compileFlags = compileFlags;
	node->has_structural_children = !(compileFlags & C_DETAIL) && !node->opaque;
	plane = &mapplanes[splitPlaneNum];
	childLists[0] = NULL;
	childLists[1] = NULL;

	splits = front = back = 0;

	for(split = list; split; split = next)
	{
		/* set next */
		next = split->next;

		/* don't split by identical plane */
		if(split->planenum == node->planenum)
		{
			FreeBspFace(split);
			continue;
		}

		if(!(split->compileFlags & C_DETAIL))
			isstruct = 1;

		/* determine which side the face falls on */
		side = WindingOnPlaneSide(split->w, plane->normal, plane->dist);

		/* switch on side */
		if(side == SIDE_CROSS)
		{
			splits++;

			ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding);
			if(frontWinding)
			{
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[0] = newFace;

				front++;
			}
			if(backWinding)
			{
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[1] = newFace;

				back++;
			}
			FreeBspFace(split);
		}
		else if(side == SIDE_FRONT)
		{
			split->next = childLists[0];
			childLists[0] = split;

			front++;
		}
		else if(side == SIDE_BACK)
		{
			split->next = childLists[1];
			childLists[1] = split;

			back++;
		}
	}


	// recursively process children
	for(i = 0; i < 2; i++)
	{
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		VectorCopy(node->mins, node->children[i]->mins);
		VectorCopy(node->maxs, node->children[i]->maxs);

		c_faceNodes++;
	}

	for(i = 0; i < 3; i++)
	{
		if(plane->normal[i] == 1)
		{
			node->children[0]->mins[i] = plane->dist;
			node->children[1]->maxs[i] = plane->dist;
			break;
		}
	}

#if 1
	if(drawBSP && drawTree)
	{
		drawChildLists[0] = childLists[0];
		drawChildLists[1] = childLists[1];
		drawSplitNode = node;
		Draw_Scene(DrawAll);
	}
#endif

#if defined(DEBUG_SPLITS)
	if((node->compileFlags & C_DETAIL) && isstruct)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf1\n", node->has_structural_children);
#endif

	for(i = 0; i < 2; i++)
	{
		BuildFaceTree_r(node->children[i], childLists[i]);
		node->has_structural_children |= node->children[i]->has_structural_children;
	}

#if defined(DEBUG_SPLITS)
	if((node->compileFlags & C_DETAIL) && !(node->children[0]->compileFlags & C_DETAIL) &&
	   node->children[0]->planenum != PLANENUM_LEAF)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural\n", node->has_structural_children);
	if((node->compileFlags & C_DETAIL) && isstruct)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf2\n", node->has_structural_children);
#endif
}
Esempio n. 9
0
//===========================================================================
// The incoming brush list will be freed before exiting
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
tree_t *BrushBSP(bspbrush_t *brushlist, vec3_t mins, vec3_t maxs)
{
	int i, c_faces, c_nonvisfaces, c_brushes;
	bspbrush_t *b;
	node_t *node;
	tree_t *tree;
	vec_t volume;
//	vec3_t point;

	Log_Print("-------- Brush BSP ---------\n");

	tree = Tree_Alloc();

	c_faces = 0;
	c_nonvisfaces = 0;
	c_brushes = 0;
	c_totalsides = 0;
	for (b = brushlist; b; b = b->next)
	{
		c_brushes++;

		volume = BrushVolume(b);
		if (volume < microvolume)
		{
			Log_Print("WARNING: entity %i, brush %i: microbrush\n",
				b->original->entitynum, b->original->brushnum);
		} //end if

		for (i=0 ; i<b->numsides ; i++)
		{
			if (b->sides[i].flags & SFL_BEVEL)
				continue;
			if (!b->sides[i].winding)
				continue;
			if (b->sides[i].texinfo == TEXINFO_NODE)
				continue;
			if (b->sides[i].flags & SFL_VISIBLE)
			{
				c_faces++;
			} //end if
			else
			{
				c_nonvisfaces++;
				//if (create_aas) b->sides[i].texinfo = TEXINFO_NODE;
			} //end if
		} //end for
		c_totalsides += b->numsides;

		AddPointToBounds (b->mins, tree->mins, tree->maxs);
		AddPointToBounds (b->maxs, tree->mins, tree->maxs);
	} //end for

	Log_Print("%6i brushes\n", c_brushes);
	Log_Print("%6i visible faces\n", c_faces);
	Log_Print("%6i nonvisible faces\n", c_nonvisfaces);
	Log_Print("%6i total sides\n", c_totalsides);

	c_active_brushes = c_brushes;
	c_nodememory = 0;
	c_brushmemory = 0;
	c_peak_brushmemory = 0;

	c_nodes = 0;
	c_nonvis = 0;
	node = AllocNode ();

	//volume of first node (head node)
	node->volume = BrushFromBounds (mins, maxs);
	//
	tree->headnode = node;
	//just get some statistics and the mins/maxs of the node
	numrecurse = 0;
//	qprintf("%6d splits", numrecurse);

	tree->headnode->brushlist = brushlist;
	BuildTree(tree);

	//build the bsp tree with the start node from the brushlist
//	node = BuildTree_r(node, brushlist);

	//if the conversion is cancelled
	if (cancelconversion) return tree;

	qprintf("\n");
	Log_Write("%6d splits\r\n", numrecurse);
//	Log_Print("%6i visible nodes\n", c_nodes/2 - c_nonvis);
//	Log_Print("%6i nonvis nodes\n", c_nonvis);
//	Log_Print("%6i leaves\n", (c_nodes+1)/2);
//	Log_Print("%6i solid leaf nodes\n", c_solidleafnodes);
//	Log_Print("%6i active brushes\n", c_active_brushes);
	if (numthreads == 1)
	{
//		Log_Print("%6i KB of node memory\n", c_nodememory >> 10);
//		Log_Print("%6i KB of brush memory\n", c_brushmemory >> 10);
//		Log_Print("%6i KB of peak brush memory\n", c_peak_brushmemory >> 10);
//		Log_Print("%6i KB of winding memory\n", WindingMemory() >> 10);
//		Log_Print("%6i KB of peak winding memory\n", WindingPeakMemory() >> 10);
		Log_Print("%6i KB of peak total bsp memory\n", c_peak_totalbspmemory >> 10);
	} //end if
Esempio n. 10
0
//thread function, gets nodes from the nodelist and processes them
void BuildTreeThread(int threadid)
{
	node_t *newnode, *node;
	side_t *bestside;
	int i, totalmem;
	bspbrush_t *brushes;

	for (node = NextNodeFromList(); node; )
	{
		//if the nodelist isn't empty try to add another thread
		//if (NodeListSize() > 10) AddThread(BuildTreeThread);
		//display the number of nodes processed so far
		if (numthreads == 1)
			IncreaseNodeCounter();

		brushes = node->brushlist;

		if (numthreads == 1)
		{
			totalmem = WindingMemory() + c_nodememory + c_brushmemory;
			if (totalmem > c_peak_totalbspmemory)
			{
				c_peak_totalbspmemory = totalmem;
			} //end if
			c_nodes++;
		} //endif

		if (drawflag)
		{
			DrawBrushList(brushes, node);
		} //end if

		if (cancelconversion)
		{
			bestside = NULL;
		} //end if
		else
		{
			// find the best plane to use as a splitter
			bestside = SelectSplitSide(brushes, node);
		} //end else
		//if there's no split side left
		if (!bestside)
		{
			//create a leaf out of the node
			LeafNode(node, brushes);
			if (node->contents & CONTENTS_SOLID) c_solidleafnodes++;
			if (create_aas)
			{
				//free up memory!!!
				FreeBrushList(node->brushlist);
				node->brushlist = NULL;
			} //end if
			//free the node volume brush (it is not used anymore)
			if (node->volume)
			{
				FreeBrush(node->volume);
				node->volume = NULL;
			} //end if
			node = NextNodeFromList();
			continue;
		} //end if

		// this is a splitplane node
		node->side = bestside;
		node->planenum = bestside->planenum & ~1;	//always use front facing

		//allocate children
		for (i = 0; i < 2; i++)
		{
			newnode = AllocNode();
			newnode->parent = node;
			node->children[i] = newnode;
		} //end for

		//split the brush list in two for both children
		SplitBrushList(brushes, node, &node->children[0]->brushlist, &node->children[1]->brushlist);

		CheckBrushLists(node->children[0]->brushlist, node->children[1]->brushlist);
		//free the old brush list
		FreeBrushList(brushes);
		node->brushlist = NULL;

		//split the volume brush of the node for the children
		SplitBrush(node->volume, node->planenum, &node->children[0]->volume,
								&node->children[1]->volume);

		if (!node->children[0]->volume || !node->children[1]->volume)
		{
			Error("child without volume brush");
		} //end if

		//free the volume brush
		if (node->volume)
		{
			FreeBrush(node->volume);
			node->volume = NULL;
		} //end if
		//add both children to the node list
		//AddNodeToList(node->children[0]);
		AddNodeToList(node->children[1]);
		node = node->children[0];
	} //end while
	RemoveThread(threadid);
} //end of the function BuildTreeThread
Esempio n. 11
0
node_t *BuildTree_r (node_t *node, bspbrush_t *brushes)
{
	node_t		*newnode;
	side_t		*bestside;
	int			i, totalmem;
	bspbrush_t	*children[2];

	qprintf("\r%6d", numrecurse);
	numrecurse++;

	if (numthreads == 1)
	{
		totalmem = WindingMemory() + c_nodememory + c_brushmemory;
		if (totalmem > c_peak_totalbspmemory)
			c_peak_totalbspmemory = totalmem;
		c_nodes++;
	} //endif

	if (drawflag)
		DrawBrushList(brushes, node);

	// find the best plane to use as a splitter
	bestside = SelectSplitSide (brushes, node);
	if (!bestside)
	{
		// leaf node
		node->side = NULL;
		node->planenum = -1;
		LeafNode(node, brushes);
		if (node->contents & CONTENTS_SOLID) c_solidleafnodes++;
		if (create_aas)
		{
			//free up memory!!!
			FreeBrushList(node->brushlist);
			node->brushlist = NULL;
			//free the node volume brush
			if (node->volume)
			{
				FreeBrush(node->volume);
				node->volume = NULL;
			} //end if
		} //end if
		return node;
	} //end if

	// this is a splitplane node
	node->side = bestside;
	node->planenum = bestside->planenum & ~1;	// always use front facing

	//split the brush list in two for both children
	SplitBrushList (brushes, node, &children[0], &children[1]);
	//free the old brush list
	FreeBrushList (brushes);

	// allocate children before recursing
	for (i = 0; i < 2; i++)
	{
		newnode = AllocNode ();
		newnode->parent = node;
		node->children[i] = newnode;
	} //end for

	//split the volume brush of the node for the children
	SplitBrush (node->volume, node->planenum, &node->children[0]->volume,
		&node->children[1]->volume);

	if (create_aas)
	{
		//free the volume brush
		if (node->volume)
		{
			FreeBrush(node->volume);
			node->volume = NULL;
		} //end if
	} //end if
	// recursively process children
	for (i = 0; i < 2; i++)
	{
		node->children[i] = BuildTree_r(node->children[i], children[i]);
	} //end for

	return node;
} //end of the function BuildTree_r
Esempio n. 12
0
/*
   PseudoCompileBSP()
   a stripped down ProcessModels
 */
void PseudoCompileBSP( qboolean need_tree, const char *BSPFilePath, const char *surfaceFilePath ){
	int models;
	char modelValue[10];
	entity_t *entity;
	face_t *faces;
	tree_t *tree;
	node_t *node;
	brush_t *brush;
	side_t *side;
	int i;

	SetDrawSurfacesBuffer();
	mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
	memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
	numMapDrawSurfs = 0;

	BeginBSPFile();
	models = 1;
	for ( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
	{
		/* get entity */
		entity = &entities[ mapEntityNum ];
		if ( entity->brushes == NULL && entity->patches == NULL ) {
			continue;
		}

		if ( mapEntityNum != 0 ) {
			sprintf( modelValue, "*%d", models++ );
			SetKeyValue( entity, "model", modelValue );
		}

		/* process the model */
		Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
		BeginModel();

		entity->firstDrawSurf = numMapDrawSurfs;

		ClearMetaTriangles();
		PatchMapDrawSurfs( entity );

		if ( mapEntityNum == 0 && need_tree ) {
			faces = MakeStructuralBSPFaceList( entities[0].brushes );
			tree = FaceBSP( faces );
			node = tree->headnode;
		}
		else
		{
			node = AllocNode();
			node->planenum = PLANENUM_LEAF;
			tree = AllocTree();
			tree->headnode = node;
		}

		/* a minimized ClipSidesIntoTree */
		for ( brush = entity->brushes; brush; brush = brush->next )
		{
			/* walk the brush sides */
			for ( i = 0; i < brush->numsides; i++ )
			{
				/* get side */
				side = &brush->sides[ i ];
				if ( side->winding == NULL ) {
					continue;
				}
				/* shader? */
				if ( side->shaderInfo == NULL ) {
					continue;
				}
				/* save this winding as a visible surface */
				DrawSurfaceForSide( entity, brush, side, side->winding );
			}
		}

		if ( meta ) {
			ClassifyEntitySurfaces( entity );
			MakeEntityDecals( entity );
			MakeEntityMetaTriangles( entity );
			SmoothMetaTriangles();
			MergeMetaTriangles();
		}
		FilterDrawsurfsIntoTree( entity, tree );

		FilterStructuralBrushesIntoTree( entity, tree );
		FilterDetailBrushesIntoTree( entity, tree );

		EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes );
		EndModel( entity, node );
	}
	EndBSPFile( qfalse, BSPFilePath, surfaceFilePath );
}