aboutsummaryrefslogtreecommitdiff
path: root/tool_src/BspLib/BSPTree.cpp
blob: 5c94dbecf7a1559e51a6a8db2255869da14674d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//-----------------------------------------------------------------------------
//	BSPLIB MODULE: BSPTree.cpp
//
//  Copyright (c) 1997-1998 by Markus Hadwiger
//  All Rights Reserved.
//-----------------------------------------------------------------------------

// bsplib header files
#include "BSPTree.h"


BSPLIB_NAMESPACE_BEGIN


#define BLOCK_SIZE 4096


// append new node to flat bsp tree -------------------------------------------
//
BSPNodeFlat *BSPTreeFlatRep::AppendNode( int front, int back, Polygon *poly, int clist, int blist )
{
	// expand storage area (array) if no space available
	if ( nodestorage - numnodes == 0 ) {
		BSPNodeFlat *newroot = new BSPNodeFlat[ nodestorage + BLOCK_SIZE ];
		if ( root != NULL ) {
			memcpy( newroot, root, nodestorage * sizeof( BSPNodeFlat ) );
			delete[] root;
		}
		root = newroot;
		nodestorage += BLOCK_SIZE;
	}
	// init new node and return its address
	root[ numnodes ].InitNode( front, back, poly, clist, blist );
	return root + numnodes++;
}


// fetch node per id (node number) --------------------------------------------
//
BSPNodeFlat *BSPTreeFlatRep::FetchNodePerId( int id )
{
	// id has to be greater than 0 since 0 means empty halfspace
	return ( ( id > 0 ) && ( id <= numnodes ) ) ? ( root + id - 1 ) : NULL;
}


// apply scale factor to separator planes and bounding boxes of all nodes -----
//
void BSPTreeFlatRep::ApplyScaleFactor( double sfac )
{
	BSPNodeFlat *scan = root;
	for ( int i = 0; i < numnodes; i++, scan++ )
		scan->ApplyScaleFactor( sfac );
}


// build pointer-based bsp tree from flat representation ----------------------
//
BSPNode *BSPTreeFlatRep::BuildBSPTree( int nodenum )
{
	if ( nodenum == 0 )
		return NULL;

	BSPNodeFlat *node = FetchNodePerId( nodenum );
	if ( node == NULL )
		return NULL;

	// get node's polygon
	Polygon	*poly = node->getPolygon();

	// append contained list to polygon (frontfacing polygons)
	static int containedindx;
	static Polygon *precpoly;
	containedindx = node->getContainedList();
	precpoly	  = poly;
	while ( containedindx > 0 ) {
		static BSPNodeFlat *cnode;
		static Polygon *cpoly;
		cnode = FetchNodePerId( containedindx );
		cpoly = cnode ? cnode->getPolygon() : NULL;
		containedindx = cnode ? cnode->getContainedList() : 0;
		precpoly->setNext( cpoly );
		precpoly = cpoly;
	}
	if ( precpoly ) {
		// detach original polygon list
		precpoly->setNext( NULL );
	}

	// build list of backfacing polygons (backlist)
	Polygon *backlist = NULL;
	containedindx	  = node->getBackList();
	precpoly		  = NULL;
	while ( containedindx > 0 ) {
		static BSPNodeFlat *cnode;
		static Polygon *cpoly;
		cnode = FetchNodePerId( containedindx );
		cpoly = cnode ? cnode->getPolygon() : NULL;
		containedindx = cnode ? cnode->getBackList() : 0;
		if ( precpoly == NULL)
			backlist = cpoly;
		else
			precpoly->setNext( cpoly );
		precpoly = cpoly;
	}
	if ( precpoly ) {
		// detach original polygon list
		precpoly->setNext( NULL );
	}

	// recursively build front- and back-subtree
	BSPNode *front = BuildBSPTree( node->getFrontSubTree() );
	BSPNode *back  = BuildBSPTree( node->getBackSubTree() );

	return new BSPNode( front, back, poly, backlist, node->getSeparatorPlane(), node->getBoundingBox() );
}


BSPLIB_NAMESPACE_END

//-----------------------------------------------------------------------------