You are here

Cells and Portals inside

General

In this demo a scene is generated by a recursive function. The scene represents a number of rooms connected with 2, 3 and 4 doors depending on the location. The use of Cells and Portals nodes with BspTree node increases the speed of the algorithm by factor of 2-3. Another similar demo for the outer arrangement of objects may be found here:

Cells and portals outside



Demo packages

(Usage Demo)
Package 1     Start   Download zip
    cells_and_portals_inside/package_01/cells_and_portals_inside.wrl




Snippets and Comments

The code of the demo consists majorily of the javascript.
In the initialize function the recursive function makeGrid is called. This function creats the scene tree:

function makeGrid(x1,x2,y1,y2,split,level)
{
	if ((level <=0) || ((split == 0) && ((x2-x1)<=1))) 
	{
		// when the leafs are reached create the geometry and cell:
		return makeRoom(x1,y1, x1*xSpacing,y1*zSpacing, x2*xSpacing,y2*zSpacing... );
	}
	if (split == 0){ // a flag pointing that splitting of X axis is due
		xc = (x1+x2) / 2;
		// go to recursion for the children nodes:
		n = makeNode(makeGrid(x1,xc,y1,y2,1,level), makeGrid(xc,x2,y1,y2,1,level),...);
		return n;
	}  else { // otherwise split along y
		yc = (y1+y2) / 2;
		// go to recursion for the children nodes:
		n = makeNode(makeGrid(x1,x2,y1,yc,0,level-1), makeGrid(x1,x2,yc,y2,0,level-1),...);
		return n;
	}
}
Build the tree

At each recursion a new node of a tree is created in the function makeNode.
Creation of new such node corresponds to the blocks of rooms produced by splitting the rooms and represented in the animated clip below.
Therefore the Bsp-Tree is built in this manner.

function makeNode(left,right,splitDim,splitOffset) 
{
	var g;
	// make the BspTree node:
	g = new SFNode('BspTree {}');
	// set the right and left children of the newly created node:
	g.set_front = left;
	g.set_back = right;

	// first set the plane's normal vector to zero-vector:
	g.plane[0]=g.plane[1]=g.plane[2]=0.0;
	
	if (splitDim == 0) // the plane's normal vector (1,0,0) : division in y direction
		g.plane[0]= 1.0;
	else g.plane[2]= 1.0; // the plane's normal vector (0,1,0) : division in x direction
	
	// the 4th element of the plane's equation: D = - (Ax +By + Cz)
	g.plane[3]= -splitOffset;
} 

When the leaves of the tree are reached the geometry is created with function makeRoom :

function makeRoom(ix,iy, x1,z1,x2,z2,height,app)
{
	// dimensions settings......

	// make a wall with door. Here the portals will be created before creation of a cell:
	makeWallWidthDoor(p2,p3,height,d1,d2,dh,ix+1,iy);

	// make a cell.
	// The portals are already prepared now and will be attached to the cell later:
	cell = makeCell(ix,iy,parts);
}
Make geometry

The makeWallWidthDoor function calls the makePortal function where a corresponding portal is created:

function makePortal(ix,iy,ofs,cnt) 
{
	// create a new portal with a unique name:
	var name = new SFString('PC'+ix+'_'+iy);
	portal = Browser.createVrmlFromString('DEF '+name+' Portal {}') [0]; 

	// prepare a container for the portal's coordinates:
	ifscoord = new SFNode('Coordinate {}');  
	ifscoord.point.length = 4;
	
	// normally a portal has a rectangular form (cnt = 4):
	for(i=0; i<cnt;i++)
	{
		ifscoord.point[i] = coord[ofs+(cnt-1)-i];
	}
	// assign the portal's coordinates:
	portal.coord = ifscoord;
	
	// add the new portal to the temporary array 
	// altogether maximum 4 portals will be stored in "portals" array for one cell (room)
	// after which the portals will be assigned to the cell and emptied.
	portals[portals.length] = portal;
}
Make geometry

Now that the portals are prepared the cell is to be created (see the makeRoom function):

function makeCell(ix,iy,children)
{
	// create a unique name consisting of the x and y coordinates of the cell.
	// For example this unique name may look as follows: C1_2
	// The name will correspond to the portal with the name PC1_2
	// However another way of matchinig cells and portals is possible.
	// This matching is needed for the resolvePortals function.

	var name = new SFString('C'+ix+'_'+iy);
	var cell;

	cell = Browser.createVrmlFromString('DEF '+name+' Cell {}') [0]; 
	// store the portals 
	cell.portals = portals;
	portals.length = 0;

	cell.set_children = children;

	// add the newly created cell into the cells array:
	cells[cells.length] = cell;

	return cell;
}
Make cell

After all cells and their portals are prepared the portals must be given the reference to the cells they are "porting" to:

// for each portal, set pointer to cell visibile through portal
function resolvePortals() 
{
	var nc=cells.length;
	for(i=0; i<nc;i++)
	{
		c=cells[i];

		np=c.portals.length;
		for (j=0; j<np; j++) {
			p = c.portals[j];
			toname = p.getName();
			toname = toname.substring(1); // eg. PC10_10.substring(1) = C10_10 (name of cell)
			// find the cell with name toname 
			for(cii=0; cii<nc;cii++) {
				if (i!=cii) 
				  if (cells[cii].getName() == toname) {
					p.cell = cells[cii];
					break;
				}	
			}	
		}	
	}	
}
Make cell
The following image represents the first two cells with their portals:

Hierarchy tree

The following gif-animation visualizes the algorithm steps:

Algorithm demonstration

The combination of the Bsp-Tree and the Cells&Portals nodes may increase the frame rate by factor 2-3.




Show other demos by:

Type: