Example #1
0
void CBuild::Light()
{
	//****************************************** Implicit
	{
		FPU::m64r		();
		Phase			("LIGHT: Implicit...");
		mem_Compact		();
		ImplicitLighting();
	}

	//****************************************** Lmaps
	{
		FPU::m64r		();
		Phase			("LIGHT: LMaps...");
		mem_Compact		();

		// Randomize deflectors
		std::random_shuffle	(g_deflectors.begin(),g_deflectors.end());
		for					(u32 dit = 0; dit<g_deflectors.size(); dit++)	task_pool.push_back(dit);

		// Main process (4 threads)
		Status			("Lighting...");
		CThreadManager	threads;
		const	u32	thNUM	= 6;
		CTimer	start_time;	start_time.Start();				
		for				(int L=0; L<thNUM; L++)	threads.start(xr_new<CLMThread> (L));
		threads.wait	(500);
		clMsg			("%f seconds",start_time.GetElapsed_sec());
	}

	//****************************************** Vertex
	FPU::m64r		();
	Phase			("LIGHT: Vertex...");
	mem_Compact		();

	LightVertex		();

	//****************************************** Merge LMAPS
	{
		FPU::m64r		();
		Phase			("LIGHT: Merging lightmaps...");
		mem_Compact		();

		xrPhase_MergeLM	();
	}
}
Example #2
0
void CBuild::SaveTREE	(IWriter &fs)
{
	CMemoryWriter		MFS;

	Status				("Geometry buffers...");
	xr_vector<u32>		remap;
	remap.reserve		(g_tree.size());
	for (u32 rid=0; rid<g_tree.size(); rid++)	{
		OGF*	o		= dynamic_cast<OGF*>	(g_tree[rid]);
		if		(o)		remap.push_back(rid);
	}
	std::stable_sort	(remap.begin(),remap.end(),remap_order);
	clMsg				("remap-size: %d / %d",remap.size(),g_tree.size());
	for (u32 sid=0; sid<remap.size(); sid++)	{
		u32				id	= remap[sid];
		//clMsg			("%3d: subdiv: %d",sid,id);
		g_tree[id]->PreSave	(id);
	}

	Status				("Visuals...");
	fs.open_chunk		(fsL_VISUALS);
	for (xr_vector<OGF_Base*>::iterator it = g_tree.begin(); it!=g_tree.end(); it++)	{
		u32			idx = u32(it-g_tree.begin());
		MFS.open_chunk	(idx);
		(*it)->Save		(MFS);
		MFS.close_chunk	();
		Progress		(float(idx)/float(g_tree.size()));
	}
	fs.w				(MFS.pointer(),MFS.size());
	fs.close_chunk		();
	clMsg				("Average: %d verts/%d faces, 50(%2.1f), 100(%2.1f), 500(%2.1f), 1000(%2.1f), 5000(%2.1f)",
		g_batch_verts/g_batch_count,
		g_batch_faces/g_batch_count,
		100.f * float(g_batch_50)/float(g_batch_count),
		100.f * float(g_batch_100)/float(g_batch_count),
		100.f * float(g_batch_500)/float(g_batch_count),
		100.f * float(g_batch_1000)/float(g_batch_count),
		100.f * float(g_batch_5000)/float(g_batch_count)
		);
	mem_Compact			();

	SaveGEOMs			("level.geom",	g_VB,g_IB,g_SWI);	// Normal
	SaveGEOMs			("level.geomx",	x_VB,x_IB,x_SWI);	// Fast-Path

	Status				("Shader table...");
	fs.open_chunk		(fsL_SHADERS);
	fs.w_u32			(g_Shaders.size());
	for (xr_vector<LPCSTR>::iterator T=g_Shaders.begin(); T!=g_Shaders.end(); T++)
		fs.w_stringZ	(*T);
	fs.close_chunk		();
	//mem_Compact			();
}
Example #3
0
void CBuild::mem_CompactSubdivs()
{
	// Memory compact
	CTimer	dwT;	dwT.Start();
	vecFace			temp;
	for (int SP = 0; SP<int(g_XSplit.size()); SP++) 
	{
		temp.clear			();
		temp.assign			(g_XSplit[SP]->begin(),g_XSplit[SP]->end());
		xr_delete			(g_XSplit[SP]);
		mem_Compact			();
		g_XSplit[SP]		= xr_new<vecFace> ();
		g_XSplit[SP]->assign(temp.begin(),temp.end());
	}
	clMsg		("%d ms for memory compacting...",dwT.GetElapsed_ms());
}
Example #4
0
void CBuild::PreOptimize()
{
	// We use overlapping hash table to avoid boundary conflicts
	vecVertex*			HASH	[HDIM_X+1][HDIM_Y+1][HDIM_Z+1];
	Fvector				VMmin,	VMscale, VMeps, scale;
	
	// Calculate offset,scale,epsilon
	Fbox				bb = scene_bb;
	VMscale.set			(bb.max.x-bb.min.x, bb.max.y-bb.min.y, bb.max.z-bb.min.z);
	VMmin.set			(bb.min);
	VMeps.set			(VMscale.x/HDIM_X/2,VMscale.y/HDIM_Y/2,VMscale.z/HDIM_Z/2);
	VMeps.x				= (VMeps.x<EPS_L)?VMeps.x:EPS_L;
	VMeps.y				= (VMeps.y<EPS_L)?VMeps.y:EPS_L;
	VMeps.z				= (VMeps.z<EPS_L)?VMeps.z:EPS_L;
	scale.set			(float(HDIM_X),float(HDIM_Y),float(HDIM_Z));
	scale.div			(VMscale);
	
	u32	Vcount		= lc_global_data()->g_vertices().size(),	Vremoved=0;
	u32	Fcount		= lc_global_data()->g_faces().size(),		Fremoved=0;
	
	// Pre-alloc memory
	int		_size	= (HDIM_X+1)*(HDIM_Y+1)*(HDIM_Z+1);
	int		_average= (Vcount/_size)/2;	if (_average<2)	_average = 2;
	{
		for (int ix=0; ix<HDIM_X+1; ix++)
			for (int iy=0; iy<HDIM_Y+1; iy++)
				for (int iz=0; iz<HDIM_Z+1; iz++)
				{
					HASH[ix][iy][iz] = new vecVertex();
					HASH[ix][iy][iz]->reserve	(_average);
				}
	}
	
	// 
	Status("Processing...");
	g_bUnregister		= false;
	for (int it = 0; it<(int)lc_global_data()->g_vertices().size(); it++)
	{
		if (0==(it%100000)) {
			Progress(_sqrt(float(it)/float(lc_global_data()->g_vertices().size())));
			Status	("Processing... (%d verts removed)",Vremoved);
		}

		if (it>=(int)lc_global_data()->g_vertices().size()) break;

		Vertex	*pTest	= lc_global_data()->g_vertices()[it];
		Fvector	&V		= pTest->P;

		// Hash
		u32 ix,iy,iz;
		ix = iFloor		((V.x-VMmin.x)*scale.x);
		iy = iFloor		((V.y-VMmin.y)*scale.y);
		iz = iFloor		((V.z-VMmin.z)*scale.z);
		R_ASSERT		(ix<=HDIM_X && iy<=HDIM_Y && iz<=HDIM_Z);
		vecVertex &H	= *(HASH[ix][iy][iz]);

		// Search similar vertices in hash table
		for (vecVertexIt T=H.begin(); T!=H.end(); T++)
		{
			Vertex *pBase = *T;
			if (pBase->similar(*pTest,g_params().m_weld_distance)) 
			{
				while(pTest->m_adjacents.size())	
					pTest->m_adjacents.front()->VReplace(pTest, pBase);

				lc_global_data()->destroy_vertex(lc_global_data()->g_vertices()[it]);
				Vremoved			+= 1;
				pTest				= NULL;
				break;
			}
		}
		
		// If we get here - there is no similar vertices - register in hash tables
		if (pTest) 
		{
			H.push_back	(pTest);

			u32 ixE,iyE,izE;
			ixE = iFloor((V.x+VMeps.x-VMmin.x)*scale.x);
			iyE = iFloor((V.y+VMeps.y-VMmin.y)*scale.y);
			izE = iFloor((V.z+VMeps.z-VMmin.z)*scale.z);
			R_ASSERT(ixE<=HDIM_X && iyE<=HDIM_Y && izE<=HDIM_Z);

			if (ixE!=ix)							HASH[ixE][iy][iz]->push_back		(pTest);
			if (iyE!=iy)							HASH[ix][iyE][iz]->push_back		(pTest);
			if (izE!=iz)							HASH[ix][iy][izE]->push_back		(pTest);
			if ((ixE!=ix)&&(iyE!=iy))				HASH[ixE][iyE][iz]->push_back		(pTest);
			if ((ixE!=ix)&&(izE!=iz))				HASH[ixE][iy][izE]->push_back		(pTest);
			if ((iyE!=iy)&&(izE!=iz))				HASH[ix][iyE][izE]->push_back		(pTest);
			if ((ixE!=ix)&&(iyE!=iy)&&(izE!=iz))	HASH[ixE][iyE][izE]->push_back		(pTest);
		}
	}
	
	Status("Removing degenerated/duplicated faces...");
	g_bUnregister	= false;
	for (u32 it=0; it<lc_global_data()->g_faces().size(); it++)
	{
		R_ASSERT		(it>=0 && it<(int)lc_global_data()->g_faces().size());
		Face* F			= lc_global_data()->g_faces()[it];
		if ( F->isDegenerated()) {
			lc_global_data()->destroy_face	(lc_global_data()->g_faces()[it]);
			Fremoved			++;
		} else {
			// Check validity
			F->Verify			( );
		}
		Progress	(float(it)/float(lc_global_data()->g_faces().size()));
	}
	if (InvalideFaces())	
	{
		err_save		();
		xrDebug::Fatal		(DEBUG_INFO,"* FATAL: %d invalid faces. Compilation aborted",InvalideFaces());
	}

	Status				("Adjacency check...");
	g_bUnregister		= false;

	for (u32 it = 0; it<lc_global_data()->g_vertices().size(); ++it)
	{
		if (lc_global_data()->g_vertices()[it] && (lc_global_data()->g_vertices()[it]->m_adjacents.empty()))
		{
			lc_global_data()->destroy_vertex	(lc_global_data()->g_vertices()[it]);
			++Vremoved;
		}
	}
	
	Status				("Cleanup...");
	lc_global_data()->g_vertices().erase	(std::remove(lc_global_data()->g_vertices().begin(),lc_global_data()->g_vertices().end(),(Vertex*)0),lc_global_data()->g_vertices().end());
	lc_global_data()->g_faces().erase		(std::remove(lc_global_data()->g_faces().begin(),lc_global_data()->g_faces().end(),(Face*)0),lc_global_data()->g_faces().end());
	{
		for (int ix=0; ix<HDIM_X+1; ix++)
			for (int iy=0; iy<HDIM_Y+1; iy++)
				for (int iz=0; iz<HDIM_Z+1; iz++)
				{
					xr_delete(HASH[ix][iy][iz]);
				}
	}
	mem_Compact			();
	clMsg("%d vertices removed. (%d left)",Vcount-lc_global_data()->g_vertices().size(),lc_global_data()->g_vertices().size());
	clMsg("%d faces removed. (%d left)",   Fcount-lc_global_data()->g_faces().size(),   lc_global_data()->g_faces().size());
	
	// -------------------------------------------------------------
	/*
	int		err_count	=0 ;
	for (int _1=0; _1<g_faces.size(); _1++)
	{
		Progress(float(_1)/float(g_faces.size()));
		for (int _2=0; _2<g_faces.size(); _2++)
		{
			if (_1==_2)		continue;
			if (FaceEqual(*g_faces[_1],*g_faces[_2]))	{
				err_count	++;
			}
		}
	}
	clMsg		("! duplicate/same faces found:%d",err_count);
	*/
	// -------------------------------------------------------------
}
Example #5
0
/*
// Iterate on edges - select with maximum error
int		callback_edge_error		(Face* F)
{
	float	max_err				= -1;
	int		max_id				= -1;
	for (u32 e=0; e<3; e++)
	{
		Vertex					*V1,*V2;
		F->EdgeVerts			(e,&V1,&V2);
		float len				= V1->P.distance_to	(V2->P);	// len
		if (len<aht_min_edge)	continue;
		if (len>max_err)
		{
			max_err = len;
			max_id	= e;
		}
	}
	if (max_id<0)				return max_id;

	// There should be an edge larger than "min_edge"
	base_color_c			c1; F->v[0]->C._get(c1);
	base_color_c			c2; F->v[1]->C._get(c2);
	base_color_c			c3; F->v[2]->C._get(c3);
	bool	b1	= fsimilar	(c1.hemi,c2.hemi,aht_min_err);
	bool	b2	= fsimilar	(c2.hemi,c3.hemi,aht_min_err);
	bool	b3	= fsimilar	(c3.hemi,c1.hemi,aht_min_err);
	if (b1 && b2 && b3)		return	-1;		// don't touch flat-shaded triangle
	else					return	max_id;	// tesselate longest edge
}
void	callback_vertex_hemi	(Vertex* V)
{
	// calc vertex attributes
	CDB::COLLIDER			DB;
	DB.ray_options			(0);
	base_color_c			vC;
	LightPoint				(&DB, RCAST_Model, vC, V->P, V->N, pBuild->L_static, LP_dont_rgb+LP_dont_sun,0);
	V->C._set				(vC);
}
int		smfVertex				(Vertex* V)
{
	return 1 + (std::lower_bound(g_vertices.begin(),g_vertices.end(),V)-g_vertices.begin());
}

void GSaveAsSMF					(LPCSTR fname)
{
	IWriter* W			= FS.w_open	(fname);
	string256 			tmp;

	// vertices
	std::sort			(g_vertices.begin(),g_vertices.end());
	for (u32 v_idx=0; v_idx<g_vertices.size(); v_idx++){
		Fvector v		= g_vertices[v_idx]->P;
		sprintf			(tmp,"v %f %f %f",v.x,v.y,-v.z);
		W->w_string		(tmp);
	}

	// transfer faces
	for (u32 f_idx=0; f_idx<g_faces.size(); f_idx++){
		Face*	t		= g_faces	[f_idx];
		sprintf			(tmp,"f %d %d %d",
			smfVertex(t->v[0]), smfVertex(t->v[2]), smfVertex(t->v[1]) 
			);
		W->w_string		(tmp);
	}

	// colors
	W->w_string			("bind c vertex");
	for (u32 v_idx=0; v_idx<g_vertices.size(); v_idx++){
		base_color_c	c;	g_vertices[v_idx]->C._get(c);
		float			h	= c.hemi/2.f;
		sprintf			(tmp,"c %f %f %f",h,h,h);
		W->w_string		(tmp);
	}
	
	FS.w_close	(W);
}
*/
void CBuild::xrPhase_AdaptiveHT	()
{
	CDB::COLLIDER	DB;
	DB.ray_options	(0);

	Status			("Tesselating...");
	if (1)
	{
		for (u32 fit=0; fit<lc_global_data()->g_faces().size(); fit++)	{		// clear split flag from all faces + calculate normals
			lc_global_data()->g_faces()[fit]->flags.bSplitted		= false;
			lc_global_data()->g_faces()[fit]->flags.bLocked			= true;
			lc_global_data()->g_faces()[fit]->CalcNormal			();
		}
		u_Tesselate		(callback_edge_longest,0,0);		// tesselate
	}

	// Tesselate + calculate
	Status			("Precalculating...");
	{
		mem_Compact					();

		// Build model
		FPU::m64r					();
		BuildRapid					(FALSE);

		// Prepare
		FPU::m64r					();
		Status						("Precalculating : base hemisphere ...");
		mem_Compact					();
		Light_prepare				();

		// calc approximate normals for vertices + base lighting
		for (u32 vit=0; vit<lc_global_data()->g_vertices().size(); vit++)	
		{
			base_color_c		vC;
			Vertex*		V		= lc_global_data()->g_vertices()[vit];
			V->normalFromAdj	();
			LightPoint			(&DB, lc_global_data()->RCAST_Model(), vC, V->P, V->N, pBuild->L_static(), LP_dont_rgb+LP_dont_sun,0);
			vC.mul				(0.5f);
			V->C._set			(vC);
		}
	}

	//////////////////////////////////////////////////////////////////////////
	/*
	Status				("Adaptive tesselation...");
	{
		for (u32 fit=0; fit<g_faces.size(); fit++)	{					// clear split flag from all faces + calculate normals
			g_faces[fit]->flags.bSplitted	= false;
			g_faces[fit]->flags.bLocked		= true;
		}
		u_Tesselate		(callback_edge_error,0,callback_vertex_hemi);	// tesselate
	}
	*/

	//////////////////////////////////////////////////////////////////////////
	Status				("Gathering lighting information...");
	u_SmoothVertColors	(5);

	//////////////////////////////////////////////////////////////////////////
	/*
	Status				("Exporting to SMF...");
	{
		string_path			fn;
		GSaveAsSMF			(strconcat(fn,pBuild->path,"hemi_source.smf"));
	}
	*/
}