コード例 #1
0
ファイル: ntl_bsptree.cpp プロジェクト: MakersF/BlenderDev
/******************************************************************************
 * subdivide tree
 *****************************************************************************/
void ntlTree::subdivide(BSPNode *node, int depth, int axis)
{
  int nextAxis=0; /* next axis to partition */
	int allTriDistSet = (1<<0)|(1<<1); // all mpTriDist flags set?
	//errorOut(" "<<node<<" depth:"<<depth<<" m:"<<node->members->size() <<"  "<<node->min<<" - "<<node->max );

  if(depth>mCurrentDepth) mCurrentDepth = depth;
  node->child[0] = node->child[1] = NULL;
	if( ( (int)node->members->size() > mMaxListLength) &&
			(depth < mMaxDepth ) 
			&& (node->cloneVec<10)
			&& (!mAbortSubdiv)
			) {

		gfxReal planeDiv = 0.499999;	// position of plane division

		// determine next subdivision axis
		int newaxis = 0;
		gfxReal extX = node->max[0]-node->min[0];
		gfxReal extY = node->max[1]-node->min[1];
		gfxReal extZ = node->max[2]-node->min[2];

		if( extY>extX  ) {
			if( extZ>extY ) {
				newaxis = 2;
			} else {
				newaxis = 1;
			}
		} else {
			if( extZ>extX ) {
				newaxis = 2;
			} else {
				newaxis = 0;
			}
		}
		axis = node->axis = newaxis;

		// init child nodes
		for( int i=0; i<2; i++) {
			/* status output */
			mCurrentNodes++;
			if(mCurrentNodes % 13973 ==0) {
				debugOutInter( "NTL Generating BSP Tree ("<<doSort<<","<<chooseAxis<<") ...  (Nodes "<< mCurrentNodes <<
						", Depth "<<mCurrentDepth<< ") " , 2, 2000);
			}

			/* create new node */
			node->child[i] = new BSPNode;
			node->child[i]->min = node->min;
			node->child[i]->max = node->max;
			node->child[i]->max = node->max;
			node->child[i]->child[0] = NULL;
			node->child[i]->child[1] = NULL;
			node->child[i]->members = NULL;
			nextAxis = (axis+1)%3;
			node->child[i]->axis = nextAxis;
			mNumNodes++;
			// abort when using 256MB only for tree...
			if(mNumNodes*sizeof(BSPNode)> 1024*1024*512) mAbortSubdiv = 1;

			/* current division plane */
			if(!i) {
				node->child[i]->min[axis] = node->min[axis];
				node->child[i]->max[axis] = node->min[axis] + planeDiv*
					(node->max[axis]-node->min[axis]);
			} else {
				node->child[i]->min[axis] = node->min[axis] + planeDiv*
					(node->max[axis]-node->min[axis]);
				node->child[i]->max[axis] = node->max[axis];
			}
		}


		/* process the two children */
		int thisTrisFor[2] = {0,0};
		int thisTriDoubles[2] = {0,0};
		for(int t=0;t<(int)node->members->size();t++) mpTriDist[t] = 0;
		for( int i=0; i<2; i++) {
			/* distribute triangles */
			int t  = 0;
			for (vector<ntlTriangle *>::iterator iter = node->members->begin();
					iter != node->members->end(); iter++ ) {

				/* add triangle, check bounding box axis */
				TriangleBBox *bbox = &mpTBB[ (*iter)->getBBoxId() ];
				bool isintersect = true;
				if( bbox->end[axis]   < node->child[i]->min[axis] ) isintersect = false;
				else if( bbox->start[axis] > node->child[i]->max[axis] ) isintersect = false;
				if(isintersect) {
					// add flag to vector 
					mpTriDist[t] |= (1<<i);
					// count no. of triangles for vector init
					thisTrisFor[i]++;
				}

				if(mpTriDist[t] == allTriDistSet) {
					thisTriDoubles[i]++;
					mTriDoubles++; // TODO check for small geo tree??
				}
				t++;
			} /* end of loop over all triangles */
		} // i

		/* distribute triangles */
		bool haveCloneVec[2] = {false, false};
		for( int i=0; i<2; i++) {
			node->child[i]->members = new vector<ntlTriangle *>( thisTrisFor[i] );
			node->child[i]->cloneVec = 0;
		}

		int tind0 = 0;
		int tind1 = 0;
		if( (!haveCloneVec[0]) || (!haveCloneVec[1]) ){
			int t  = 0; // triangle index counter
			for (vector<ntlTriangle *>::iterator iter = node->members->begin();
					iter != node->members->end(); iter++ ) {
				if(!haveCloneVec[0]) {
					if( (mpTriDist[t] & 1) == 1) {
						(*node->child[0]->members)[tind0] = (*iter); // dont use push_back for preinited size!
						tind0++;
					}
				}
				if(!haveCloneVec[1]) {
					if( (mpTriDist[t] & 2) == 2) {
						(*node->child[1]->members)[tind1] = (*iter); // dont use push_back for preinited size!
						tind1++;
					}
				}
				t++;
			} /* end of loop over all triangles */
		}

		// subdivide children
		for( int i=0; i<2; i++) {
			/* recurse */
			subdivide( node->child[i], depth+1, nextAxis );
		}

		/* if we are here, this are childs, so we dont need the members any more... */
		/* delete unecessary members */
		if( (!haveCloneVec[0]) && (!haveCloneVec[1]) && (node->cloneVec == 0) ){ 
			delete node->members; 
		}
		node->members = NULL;

	} /* subdivision necessary */
}
コード例 #2
0
ファイル: ntl_world.cpp プロジェクト: rexbron/blender-ocio
/******************************************************************************
 * Render the current scene
 * uses the global variables from the parser
 *****************************************************************************/
int ntlWorld::renderScene( void )
{
#ifndef ELBEEM_PLUGIN
	char nrStr[5];														// nr conversion 
	std::ostringstream outfn_conv("");  			// converted ppm with other suffix 
  ntlRenderGlobals *glob;                  	// storage for global rendering parameters 
  myTime_t timeStart,totalStart,timeEnd; 		// measure user running time 
  myTime_t rendStart,rendEnd;            		// measure user rendering time 
  glob = mpGlob;

	// deactivate for all with index!=0 
	if((glob_mpactive)&&(glob_mpindex>0)) return(0);

	/* check if picture already exists... */
	if(!glob->getSingleFrameMode() ) {
		snprintf(nrStr, 5, "%04d", glob->getAniCount() );

		if(glob_mpactive) {
			outfn_conv  << glob->getOutFilename() <<"_"<<glob_mpindex<<"_" << nrStr << ".png"; /// DEBUG!
		} else {
			// ORG
			outfn_conv  << glob->getOutFilename() <<"_" << nrStr << ".png";
		}
		
		//if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) {
		if(mpGlob->getFrameSkip()) {
			struct stat statBuf;
			if(stat(outfn_conv.str().c_str(),&statBuf) == 0) {
				errorOut("ntlWorld::renderscene Warning: file "<<outfn_conv.str()<<" already exists - skipping frame..."); 
				glob->setAniCount( glob->getAniCount() +1 );
				return(2);
			}
		} // RAY mode
	} else {
		// single frame rendering, overwrite if necessary...
		outfn_conv << glob->getSingleFrameFilename();
	}

  /* start program */
	timeStart = getTime();

	/* build scene geometry, calls buildScene(t,false) */
	glob->getRenderScene()->prepareScene(mSimulationTime);

  /* start program */
	totalStart = getTime();


	/* view parameters are currently not animated */
	/* calculate rays through projection plane */
	ntlVec3Gfx direction = glob->getLookat() - glob->getEye();
	/* calculate width of screen using perpendicular triangle diven by
	 * viewing direction and screen plane */
	gfxReal screenWidth = norm(direction)*tan( (glob->getFovy()*0.5/180.0)*M_PI );

	/* calculate vector orthogonal to up and viewing direction */
	ntlVec3Gfx upVec = glob->getUpVec();
	ntlVec3Gfx rightVec( cross(upVec,direction) );
	normalize(rightVec);

	/* calculate screen plane up vector, perpendicular to viewdir and right vec */
	upVec = ntlVec3Gfx( cross(rightVec,direction) );
	normalize(upVec);

	/* check if vectors are valid */
	if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) {
		errMsg("ntlWorld::renderScene","Invalid viewpoint vectors! up="<<upVec<<" right="<<rightVec);
		return(1);
	}

	/* length from center to border of screen plane */
	rightVec *= (screenWidth*glob->getAspect() * -1.0);
	upVec *= (screenWidth * -1.0);

	/* screen traversal variables */
	ntlVec3Gfx screenPos;                          /* current position on virtual screen */
	int Xres = glob->getResX();                  /* X resolution */
	int Yres = glob->getResY();                  /* Y resolution */
	ntlVec3Gfx rightStep = (rightVec/(Xres/2.0));  /* one step right for a pixel */
	ntlVec3Gfx upStep    = (upVec/(Yres/2.0));     /* one step up for a pixel */
    

	/* anti alias init */
	char  showAAPic = 0;
	int   aaDepth = glob->getAADepth();
	int   aaLength;
	if(aaDepth>=0) aaLength = (2<<aaDepth);
	else           aaLength = 0;
	float aaSensRed   = 0.1;
	float aaSensGreen = 0.1;
	float aaSensBlue  = 0.1;
	int   aaArrayX = aaLength*Xres+1;
	int   aaArrayY = ( aaLength+1 );
	ntlColor *aaCol = new ntlColor[ aaArrayX*aaArrayY ];
	char  *aaUse = new char[ aaArrayX*aaArrayY ];

	/* picture storage */
	int picX = Xres;
	int picY = Yres;
	if(showAAPic) {
		picX = Xres *aaLength+1;
		picY = Yres *aaLength+1;
	}
	ntlColor *finalPic = new ntlColor[picX * picY];


	/* reset picture vars */
	for(int j=0;j<aaArrayY;j++) {
		for(int i=0;i<aaArrayX;i++) {
			aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0);
			aaUse[j*aaArrayX+i] = 0;
		}
	}
	for(int j=0;j<picY;j++) {
		for(int i=0;i<picX;i++) {
			finalPic[j*picX+i] = ntlColor(0.0, 0.0, 0.0);
		}
	}

	/* loop over all y lines in screen, from bottom to top because
	 * ppm format wants 0,0 top left */
	rendStart = getTime();
	glob->setCounterShades(0);
	glob->setCounterSceneInter(0);
	for (int scanline=Yres ; scanline > 0 ; --scanline) {
    
		debugOutInter( "ntlWorld::renderScene: Line "<<scanline<<
								 " ("<< ((Yres-scanline)*100/Yres) <<"%) ", 2, 2000 );
		screenPos = glob->getLookat() + upVec*((2.0*scanline-Yres)/Yres)
			- rightVec;

		/* loop over all pixels in line */
		for (int sx=0 ; sx < Xres ; ++sx) {

			if((sx==glob->getDebugPixelX())&&(scanline==(Yres-glob->getDebugPixelY()) )) {
				// DEBUG!!!
				glob->setDebugOut(10);
			} else glob->setDebugOut(0);
			
			/* compute ray from eye through current pixel into scene... */
			ntlColor col;
			if(aaDepth<0) {
				ntlVec3Gfx dir(screenPos - glob->getEye());
				ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob );

				/* ...and trace it */
				col = the_ray.shade();
			} else {
				/* anti alias */
				int ai,aj;                   /* position in grid */
				int aOrg = sx*aaLength;      /* grid offset x */
				int currStep = aaLength;     /* step size */
				char colDiff = 1;            /* do colors still differ too much? */
				ntlColor minCol,maxCol;         /* minimum and maximum Color Values */
				minCol = ntlColor(1.0,1.0,1.0);
				maxCol = ntlColor(0.0,0.0,0.0);

				while((colDiff) && (currStep>0)) {
					colDiff = 0;
	    
					for(aj = 0;aj<=aaLength;aj+= currStep) {
						for(ai = 0;ai<=aaLength;ai+= currStep) {

							/* shade pixel if not done */
							if(aaUse[aj*aaArrayX +ai +aOrg] == 0) {
								aaUse[aj*aaArrayX +ai +aOrg] = 1;
								ntlVec3Gfx aaPos( screenPos +
																(rightStep * (ai- aaLength/2)/(gfxReal)aaLength ) +
																(upStep    * (aj- aaLength/2)/(gfxReal)aaLength ) );

								ntlVec3Gfx dir(aaPos - glob->getEye());
								ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob );

								/* ...and trace it */
								ntlColor newCol= the_ray.shade();
								aaCol[aj*aaArrayX +ai +aOrg]= newCol;
							} /* not used? */

						}
					}

					/* check color differences */
					for(aj = 0;aj<aaLength;aj+= currStep) {
						for(ai = 0;ai<aaLength;ai+= currStep) {

							char thisColDiff = 0;
							if( 
								 (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - 
											 aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) ||
								 (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - 
											 aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) ||
								 (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - 
											 aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) {
								thisColDiff = 1;
							} else
								if( 
									 (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - 
												 aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][0])> aaSensRed ) ||
									 (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - 
												 aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][1])> aaSensGreen ) ||
									 (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - 
												 aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][2])> aaSensBlue ) ) {
									thisColDiff = 1;
								} else
									if( 
										 (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - 
													 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) ||
										 (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - 
													 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) ||
										 (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - 
													 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) {
										thisColDiff = 1;
									} 

							//colDiff =1;
							if(thisColDiff) {
								/* set diff flag */
								colDiff = thisColDiff;
								for(int bj=aj;bj<=aj+currStep;bj++) {
									for(int bi=ai;bi<=ai+currStep;bi++) {
										if(aaUse[bj*aaArrayX +bi +aOrg]==2) {
											//if(showAAPic) 
											aaUse[bj*aaArrayX +bi +aOrg] = 0;
										}
									}
								}
							} else {
								/* set all values */
								ntlColor avgCol = (
																	 aaCol[(aj+0       )*aaArrayX +(ai+0       ) +aOrg] +
																	 aaCol[(aj+0       )*aaArrayX +(ai+currStep) +aOrg] +
																	 aaCol[(aj+currStep)*aaArrayX +(ai+0       ) +aOrg] +
																	 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg] ) *0.25;
								for(int bj=aj;bj<=aj+currStep;bj++) {
									for(int bi=ai;bi<=ai+currStep;bi++) {
										if(aaUse[bj*aaArrayX +bi +aOrg]==0) {
											aaCol[bj*aaArrayX +bi +aOrg] = avgCol; 
											aaUse[bj*aaArrayX +bi +aOrg] = 2;
										}
									}
								}
							} /* smaller values set */

						}
					}

					/* half step size */
					currStep /= 2;

				} /* repeat until diff not too big */

				/* get average color */
				gfxReal colNum = 0.0;
				col = ntlColor(0.0, 0.0, 0.0);
				for(aj = 0;aj<=aaLength;aj++) {
					for(ai = 0;ai<=aaLength;ai++) {
						col += aaCol[aj*aaArrayX +ai +aOrg];
						colNum += 1.0;
					}
				}
				col /= colNum;

			}

		  /* mark pixels with debugging */
			if( glob->getDebugOut() > 0) col = ntlColor(0,1,0);

			/* store pixel */
			if(!showAAPic) {
				finalPic[(scanline-1)*picX+sx] = col; 
			}
			screenPos +=  rightStep;

		} /* foreach x */

		/* init aa array */
		if(showAAPic) {
			for(int j=0;j<=aaArrayY-1;j++) {
				for(int i=0;i<=aaArrayX-1;i++) {
					if(aaUse[j*aaArrayX +i]==1) finalPic[((scanline-1)*aaLength +j)*picX+i][0] = 1.0;
				}
			}
		}

		for(int i=0;i<aaArrayX;i++) {
			aaCol[(aaArrayY-1)*aaArrayX+i] = aaCol[0*aaArrayX+i];
			aaUse[(aaArrayY-1)*aaArrayX+i] = aaUse[0*aaArrayX+i];
		}
		for(int j=0;j<aaArrayY-1;j++) {
			for(int i=0;i<aaArrayX;i++) {
				aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0);
				aaUse[j*aaArrayX+i] = 0;
			}
		}

	} /* foreach y */
	rendEnd = getTime();


	/* write png file */
	{
		int w = picX;
		int h = picY;

		unsigned rowbytes = w*4;
		unsigned char *screenbuf, **rows;
		screenbuf = (unsigned char*)malloc( h*rowbytes );
		rows = (unsigned char**)malloc( h*sizeof(unsigned char*) );
		unsigned char *filler = screenbuf;

		// cutoff color values 0..1
		for(int j=0;j<h;j++) {
			for(int i=0;i<w;i++) {
				ntlColor col = finalPic[j*w+i];
				for (unsigned int cc=0; cc<3; cc++) {
					if(col[cc] <= 0.0) col[cc] = 0.0;
					if(col[cc] >= 1.0) col[cc] = 1.0;
				}
				*filler = (unsigned char)( col[0]*255.0 ); 
				filler++;
				*filler = (unsigned char)( col[1]*255.0 ); 
				filler++;
				*filler = (unsigned char)( col[2]*255.0 ); 
				filler++;
				*filler = (unsigned char)( 255.0 ); 
				filler++; // alpha channel
			}
		}

		for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ];
		writePng(outfn_conv.str().c_str(), rows, w, h);
	}


	// next frame 
	glob->setAniCount( glob->getAniCount() +1 );

	// done 
	timeEnd = getTime();

	char resout[1024];
	snprintf(resout,1024, "NTL Done %s, frame %d/%d (took %s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n", 
				 outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1),
				 getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(),
				 glob->getCounterShades(),
				 glob->getCounterSceneInter() );
	debMsgStd("ntlWorld::renderScene",DM_MSG, resout, 1 );

	/* clean stuff up */
	delete [] aaCol;
	delete [] aaUse;
	delete [] finalPic;
	glob->getRenderScene()->cleanupScene();

	if(mpGlob->getSingleFrameMode() ) {
		debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 );
		return 1;
	}
#endif // ELBEEM_PLUGIN
	return 0;
}
コード例 #3
0
ファイル: ntl_bsptree.cpp プロジェクト: MakersF/BlenderDev
//ntlTree::ntlTree(int depth, int objnum, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, vector<ntlTriangle> *trilist) :
ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) :
  mStart(0.0), mEnd(0.0), mMaxDepth( depth ), mMaxListLength( objnum ), mpRoot( NULL) ,
  mpNodeStack( NULL), mpTBB( NULL ),
	mTriangleMask( 0xFFFF ),
  mCurrentDepth(0), mCurrentNodes(0), mTriDoubles(0)
{  
	// init scene data pointers
	mpVertices = scene->getVertexPointer();
	mpVertNormals = scene->getVertexNormalPointer();
	mpTriangles = scene->getTrianglePointer();
	mTriangleMask = triFlagMask;

  if(mpTriangles == NULL) {
    errFatal( "ntlTree Cons","no triangle list!\n",SIMWORLD_INITERROR);
    return;
  }
  if(mpTriangles->size() == 0) {
    warnMsg( "ntlTree::ntlTree","No triangles ("<< mpTriangles->size()  <<")!\n");
		mStart = mEnd = ntlVec3Gfx(0,0,0);
    return;
  }
  if(depth>=BSP_STACK_SIZE) {
    errFatal( "ntlTree::ntlTree","Depth to high ("<< mMaxDepth  <<")!\n", SIMWORLD_INITERROR );
    return;
  }

  /* check triangles (a bit inefficient, but we dont know which vertices belong
     to this tree), and generate bounding boxes */
	mppTriangles = new vector<ntlTriangle *>;
	int noOfTriangles = mpTriangles->size();
	mpTBB = new TriangleBBox[ noOfTriangles ];
	int bbCount = 0;
  mStart = mEnd = (*mpVertices)[ mpTriangles->front().getPoints()[0] ];
	//errMsg("TreeDebug","Start");
  for (vector<ntlTriangle>::iterator iter = mpTriangles->begin();
       iter != mpTriangles->end(); 
       iter++ ) {
		//errorOut(" d "<< convertFlags2String((int)(*iter).getFlags()) <<" "<< convertFlags2String( (int)mTriangleMask)<<" add? "<<( ((int)(*iter).getFlags() & (int)mTriangleMask) != 0 ) );
		// discard triangles that dont match mask
		if( ((int)(*iter).getFlags() & (int)mTriangleMask) == 0 ) {
			continue;
		}

		// test? TODO
		ntlVec3Gfx tnormal = (*mpVertNormals)[ (*iter).getPoints()[0] ]+
			(*mpVertNormals)[ (*iter).getPoints()[1] ]+
			(*mpVertNormals)[ (*iter).getPoints()[2] ];
		ntlVec3Gfx triangleNormal = (*iter).getNormal();
		if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) continue;
		if( equal(       tnormal, ntlVec3Gfx(0.0)) ) continue;
		// */

		ntlVec3Gfx bbs, bbe;
		//errMsg("TreeDebug","Triangle");
		for(int i=0;i<3;i++) {
			int index = (*iter).getPoints()[i];
			ntlVec3Gfx tp = (*mpVertices)[ index ];
			//errMsg("TreeDebug","  Point "<<i<<" = "<<tp<<" ");
			if(tp[0] < mStart[0]) mStart[0]= tp[0];
			if(tp[0] > mEnd[0])   mEnd[0]= tp[0];
			if(tp[1] < mStart[1]) mStart[1]= tp[1];
			if(tp[1] > mEnd[1])   mEnd[1]= tp[1];
			if(tp[2] < mStart[2]) mStart[2]= tp[2];
			if(tp[2] > mEnd[2])   mEnd[2]= tp[2];
			if(i==0) {
				bbs = bbe = tp; 
			} else {
				if( tp[0] < bbs[0] ) bbs[0] = tp[0];
				if( tp[0] > bbe[0] ) bbe[0] = tp[0];
				if( tp[1] < bbs[1] ) bbs[1] = tp[1];
				if( tp[1] > bbe[1] ) bbe[1] = tp[1];
				if( tp[2] < bbs[2] ) bbs[2] = tp[2];
				if( tp[2] > bbe[2] ) bbe[2] = tp[2];
			}
		}
		mppTriangles->push_back( &(*iter) );
		//errMsg("TreeDebug","Triangle "<<(*mpVertices)[(*iter).getPoints()[0]]<<" "<<(*mpVertices)[(*iter).getPoints()[1]]<<" "<<(*mpVertices)[(*iter).getPoints()[2]]<<" ");

		// add BB
		mpTBB[ bbCount ].start = bbs;
		mpTBB[ bbCount ].end = bbe;
		(*iter).setBBoxId( bbCount );
		bbCount++;
  }
	
	

  /* slighlty enlarge bounding tolerance for tree 
     to avoid problems with triangles paralell to slabs */
  mStart -= ntlVec3Gfx( getVecEpsilon() );
  mEnd   += ntlVec3Gfx( getVecEpsilon() );

  /* init root node and stack */
  mpNodeStack = new BSPStack;
  mpRoot = new BSPNode;
  mpRoot->min = mStart;
  mpRoot->max = mEnd;
  mpRoot->axis = AXIS_X;
  mpRoot->members = mppTriangles;
	mpRoot->child[0] = mpRoot->child[1] = NULL;
	mpRoot->cloneVec = 0;
	globalSortingPoints = mpVertices;
	mpTriDist = new char[ mppTriangles->size() ];
	mNumNodes = 1;
	mAbortSubdiv = 0;

  /* create tree */
  debugOutInter( "Generating BSP Tree...  (Nodes "<< mCurrentNodes <<
						", Depth "<<mCurrentDepth<< ") ", 2, 2000 );
  subdivide(mpRoot, 0, AXIS_X);
  debMsgStd("ntlTree::ntlTree",DM_MSG,"Generated Tree: Nodes "<< mCurrentNodes <<
							 ", Depth "<<mCurrentDepth<< " with "<<noOfTriangles<<" triangles", 2 );

	delete [] mpTriDist;
	delete [] mpTBB;
	mpTriDist = NULL;
	mpTBB = NULL;

	/* calculate some stats about tree */
	int noLeafs = 0;
	gfxReal avgDepth = 0.0;
	gfxReal triPerLeaf = 0.0;
	int totalTris = 0;
	
	calcStats(mpRoot,0, noLeafs, avgDepth, triPerLeaf, totalTris);
	avgDepth /= (gfxReal)noLeafs;
	triPerLeaf /= (gfxReal)noLeafs;
	debMsgStd("ntlTree::ntlTree",DM_MSG,"Tree ("<<doSort<<","<<chooseAxis<<") Stats: Leafs:"<<noLeafs<<", avgDepth:"<<avgDepth<<
			", triPerLeaf:"<<triPerLeaf<<", triDoubles:"<<mTriDoubles<<", totalTris:"<<totalTris
			<<" nodes:"<<mNumNodes
			//<<" T"<< (totalTris%3)  // 0=ich, 1=f, 2=a
			, 2 );

	if(mAbortSubdiv) {
		errMsg("ntlTree::ntlTree","Aborted... "<<mNumNodes);
  	deleteNode(mpRoot);
		mpRoot = NULL;
	}
}