Exemplo n.º 1
0
    virtual void		Execute()
    {
        CDB::COLLIDER DB;
        DB.ray_options	(CDB::OPT_ONLYFIRST);

        xr_vector<R_Light>	Lights = g_lights;

        Fvector			P,D,PLP;
        D.set			(0,1,0);
        float coeff		= 0.5f*g_params.fPatchSize/float(LIGHT_Count);

        LSelection		Selected;
        float			LperN	= float(g_lights.size());
        for (u32 i=Nstart; i<Nend; i++)
        {
            vertex& N = g_nodes[i];

            // select lights
            Selected.clear();
            for (u32 L=0; L<Lights.size(); L++)
            {
                R_Light&	R = g_lights[L];
                if (R.type==LT_DIRECT)	Selected.push_back(&R);
                else {
                    float dist = N.Pos.distance_to(R.position);
                    if (dist-g_params.fPatchSize < R.range)
                        Selected.push_back(&R);
                }
            }
            LperN = 0.9f*LperN + 0.1f*float(Selected.size());

            // lighting itself
            float amount=0;
            for (int x=-LIGHT_Count; x<=LIGHT_Count; x++)
            {
                P.x = N.Pos.x + coeff*float(x);
                for (int z=-LIGHT_Count; z<=LIGHT_Count; z++)
                {
                    // compute position
                    P.z = N.Pos.z + coeff*float(z);
                    P.y = N.Pos.y;
                    N.Plane.intersectRayPoint(P,D,PLP);	// "project" position
                    P.y = PLP.y;

                    // light point
                    amount += LightPoint(DB,P,N.Plane.n,Selected);
                }
            }

            // calculation of luminocity
            N.LightLevel	= amount/float(LIGHT_Total);

            thProgress		= float(i-Nstart)/float(Nend-Nstart);
        }
    }
Exemplo n.º 2
0
	virtual void		Execute	()
	{
		CDB::COLLIDER	DB;
		DB.ray_options	(0);
		
		u32	counter		= 0;
		for (;; counter++)
		{
			u32 id				= VLT.get();
			if (id==VLT_END)	break;

			Vertex* V		= g_vertices[id];
			R_ASSERT		(V);
			
			// Get transluency factor
			float		v_trans		= 0.f;
			BOOL		bVertexLight= FALSE;
			u32 		L_flags		= 0;
			for (u32 f=0; f<V->adjacent.size(); f++)
			{
				Face*	F								=	V->adjacent		[f];
				v_trans									+=	F->Shader().vert_translucency;
				if	(F->Shader().flags.bLIGHT_Vertex)	bVertexLight		= TRUE;
			}
			v_trans				/=	float(V->adjacent.size());

			// 
			if (bVertexLight)	{
				base_color_c		vC, old;
				V->C._get			(old);
				LightPoint			(&DB, RCAST_Model, vC, V->P, V->N, pBuild->L_static, (b_nosun?LP_dont_sun:0)|LP_dont_hemi, 0);
				vC._tmp_			= v_trans;
				vC.mul				(.5f);
				vC.hemi				= old.hemi;			// preserve pre-calculated hemisphere
				V->C._set			(vC);
				g_trans_register	(V);
			}

			thProgress			= float(counter) / float(g_vertices.size());
		}
	}
Exemplo n.º 3
0
void CDeflector::L_Direct_Edge (CDB::COLLIDER* DB, base_lighting* LightsSelected, Fvector2& p1, Fvector2& p2, Fvector& v1, Fvector& v2, Fvector& N, float texel_size, Face* skip)
{
	Fvector		vdir;
	vdir.sub	(v2,v1);
	
	lm_layer&	lm	= layer;
	
	Fvector2		size; 
	size.x			= p2.x-p1.x;
	size.y			= p2.y-p1.y;
	int	du			= iCeil(_abs(size.x)/texel_size);
	int	dv			= iCeil(_abs(size.y)/texel_size);
	int steps		= _max(du,dv);
	if (steps<=0)	return;
	
	for (int I=0; I<=steps; I++)
	{
		float	time = float(I)/float(steps);
		Fvector2	uv;
		uv.x	= size.x*time+p1.x;
		uv.y	= size.y*time+p1.y;
		int	_x  = iFloor(uv.x*float(lm.width)); 
		int _y	= iFloor(uv.y*float(lm.height));
		
		if ((_x<0)||(_x>=(int)lm.width))	continue;
		if ((_y<0)||(_y>=(int)lm.height))	continue;
		
		if (lm.marker[_y*lm.width+_x])		continue;
		
		// ok - perform lighting
		base_color_c	C;
		Fvector			P;	P.mad(v1,vdir,time);
		LightPoint		(DB, RCAST_Model, C, P, N, *LightsSelected, (b_norgb?LP_dont_rgb:0)|(b_nosun?LP_dont_sun:0)|LP_DEFAULT, skip); //.
		
		C.mul		(.5f);
		lm.surface	[_y*lm.width+_x]._set	(C);
		lm.marker	[_y*lm.width+_x]		= 255;
	}
}
Exemplo n.º 4
0
void CDeflector::L_Direct	(CDB::COLLIDER* DB, base_lighting* LightsSelected, HASH& H)
{
	R_ASSERT	(DB);
	R_ASSERT	(LightsSelected);

	lm_layer&	lm = layer;

	// Setup variables
	Fvector2	dim,half;
	dim.set		(float(lm.width),float(lm.height));
	half.set	(.5f/dim.x,.5f/dim.y);
	
	// Jitter data
	Fvector2	JS;
	JS.set		(.4999f/dim.x, .4999f/dim.y);
	
	u32			Jcount;
	Fvector2*	Jitter;
	Jitter_Select(Jitter, Jcount);
	
	// Lighting itself
	DB->ray_options	(0);
	
	for (u32 V=0; V<lm.height; V++)	{
		for (u32 U=0; U<lm.width; U++)	{
			u32				Fcount	= 0;
			base_color_c	C;
			
			try {
				for (u32 J=0; J<Jcount; J++) 
				{
					// LUMEL space
					Fvector2 P;
					P.x = float(U)/dim.x + half.x + Jitter[J].x * JS.x;
					P.y = float(V)/dim.y + half.y + Jitter[J].y * JS.y;
					
					xr_vector<UVtri*>&	space	= H.query(P.x,P.y);
					
					// World space
					Fvector		wP,wN,B;
					for (UVtri** it=&*space.begin(); it!=&*space.end(); it++)
					{
						if ((*it)->isInside(P,B)) {
							// We found triangle and have barycentric coords
							Face	*F	= (*it)->owner;
							Vertex	*V1 = F->v[0];
							Vertex	*V2 = F->v[1];
							Vertex	*V3 = F->v[2];
							wP.from_bary(V1->P,V2->P,V3->P,B);
//. не нужно использовать	if (F->Shader().flags.bLIGHT_Sharp)	{ wN.set(F->N); }
//							else								
							{ 
								wN.from_bary(V1->N,V2->N,V3->N,B);	exact_normalize	(wN); 
								wN.add		(F->N);					exact_normalize	(wN);
							}
							try {
								LightPoint	(DB, RCAST_Model, C, wP, wN, *LightsSelected, (b_norgb?LP_dont_rgb:0)|(b_nosun?LP_dont_sun:0)|LP_UseFaceDisable, F); //.
								Fcount		+= 1;
							} catch (...) {
								clMsg("* ERROR (CDB). Recovered. ");
							}
							break;
						}
					}
				} 
			} catch (...) {
				clMsg("* ERROR (Light). Recovered. ");
			}
			
			if (Fcount) {
				C.scale			(Fcount);
				C.mul			(.5f);
				lm.surface		[V*lm.width+U]._set(C);
				lm.marker		[V*lm.width+U] = 255;
			} else {
				lm.surface		[V*lm.width+U]._set(C);	// 0-0-0-0-0
				lm.marker		[V*lm.width+U] = 0;
			}
		}
	}
	// *** Render Edges
	float texel_size = (1.f/float(_max(lm.width,lm.height)))/8.f;
	for (u32 t=0; t<UVpolys.size(); t++)
	{
		UVtri&		T	= UVpolys[t];
		Face*		F	= T.owner;
		R_ASSERT	(F);
		try {
			L_Direct_Edge	(DB,LightsSelected, T.uv[0], T.uv[1], F->v[0]->P, F->v[1]->P, F->N, texel_size,F);
			L_Direct_Edge	(DB,LightsSelected, T.uv[1], T.uv[2], F->v[1]->P, F->v[2]->P, F->N, texel_size,F);
			L_Direct_Edge	(DB,LightsSelected, T.uv[2], T.uv[0], F->v[2]->P, F->v[0]->P, F->N, texel_size,F);
		} catch (...)
		{
			clMsg("* ERROR (Edge). Recovered. ");
		}
	}
}
Exemplo n.º 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"));
	}
	*/
}
//-----------------------------------------------------------------------
void xrMU_Model::calc_lighting	(xr_vector<base_color>& dest, const Fmatrix& xform, CDB::MODEL* MDL, base_lighting& lights, u32 flags)
{
	// trans-map
	typedef	xr_multimap<float,v_vertices>	mapVert;
	typedef	mapVert::iterator				mapVertIt;
	mapVert									g_trans;
	u32										I;

	// trans-epsilons
	const float eps			= EPS_L;
	const float eps2		= 2.f*eps;

	// calc pure rotation matrix
	Fmatrix Rxform,tmp,R;
	R.set						(xform	);
	R.translate_over			(0,0,0	);
	tmp.transpose				(R		);
	Rxform.invert				(tmp	);

	// Perform lighting
	CDB::COLLIDER				DB;
	DB.ray_options				(0);

	// Disable faces if needed
	/*
	BOOL bDisableFaces			= flags&LP_UseFaceDisable;
	if	(bDisableFaces)
		for (I=0; I<m_faces.size(); I++)	m_faces[I]->flags.bDisableShadowCast	= true;
	*/

	// Perform lighting
	for (I = 0; I<m_vertices.size(); I++)
	{
		_vertex*	V			= m_vertices[I];

		// Get ambient factor
		float		v_amb		= 0.f;
		float		v_trans		= 0.f;
		for (u32 f=0; f<V->m_adjacents.size(); f++)
		{
			_face*	F			=	V->m_adjacents[f];
			v_amb				+=	F->Shader().vert_ambient;
			v_trans				+=	F->Shader().vert_translucency;
		}
		v_amb					/=	float(V->m_adjacents.size());
		v_trans					/=	float(V->m_adjacents.size());
		float v_inv				=	1.f-v_amb;

		base_color_c			vC;
		Fvector					vP,vN;
		xform.transform_tiny	(vP,V->P);
		Rxform.transform_dir	(vN,V->N);
		exact_normalize			(vN); 

		// multi-sample
		const int n_samples		= (g_params().m_quality==ebqDraft)?1:6;
		for (u32 sample=0; sample<(u32)n_samples; sample++)
		{
			float				a	= 0.2f * float(sample) / float(n_samples);
			Fvector				P,N;
			N.random_dir		(vN,deg2rad(30.f));
			P.mad				(vP,N,a);
			LightPoint			(&DB, MDL, vC, P, N, lights, flags, 0);
		}
		vC.scale				(n_samples);
		vC._tmp_				=	v_trans;
		if (flags&LP_dont_hemi) ;
		else					vC.hemi	+=	v_amb;
		V->C._set				(vC);

		// Search
		const float key			= V->P.x;
		mapVertIt	it			= g_trans.lower_bound	(key);
		mapVertIt	it2			= it;

		// Decrement to the start and inc to end
		while (it!=g_trans.begin() && ((it->first+eps2)>key)) it--;
		while (it2!=g_trans.end() && ((it2->first-eps2)<key)) it2++;
		if (it2!=g_trans.end())	it2++;

		// Search
		BOOL	found = FALSE;
		for (; it!=it2; it++)
		{
			v_vertices&	VL		= it->second;
			_vertex* Front		= VL.front();
			R_ASSERT			(Front);
			if (Front->P.similar(V->P,eps))
			{
				found				= TRUE;
				VL.push_back		(V);
			}
		}

		// Register
		if (!found)				{
			mapVertIt	ins			= g_trans.insert(mk_pair(key,v_vertices()));
			ins->second.reserve		(32);
			ins->second.push_back	(V);
		}
	}

	// Enable faces if needed
	/*
	if	(bDisableFaces)
		for (I=0; I<m_faces.size(); I++)	m_faces[I]->flags.bDisableShadowCast	= true;
	*/

	// Process all groups
	for (mapVertIt it=g_trans.begin(); it!=g_trans.end(); it++)
	{
		// Unique
		v_vertices&	VL		= it->second;
		std::sort			(VL.begin(),VL.end());
		VL.erase			(std::unique(VL.begin(),VL.end()),VL.end());

		// Calc summary color
		base_color_c	C;
		for (int v=0; v<int(VL.size()); v++)
		{
			base_color_c	vC;
			VL[v]->C._get	(vC);
			C.max			(vC);
		}

		// Calculate final vertex color
		for (u32 v=0; v<int(VL.size()); v++)
		{
			base_color_c		vC;
			VL[v]->C._get		(vC);

			// trans-level
			float	level		= vC._tmp_;

			// 
			base_color_c		R;
			R.lerp				(vC,C,level);
			R.max				(vC);
			R.mul				(.5f);
			VL[v]->C._set		(R);
		}
	}

	// Transfer colors to destination
	dest.resize				(m_vertices.size());
	for (I = 0; I<m_vertices.size(); I++)
	{
		Fvector		ptPos	= m_vertices[I]->P;
		base_color	ptColor	= m_vertices[I]->C;
		dest[I]				= ptColor;
	}
}