void write( IWriter	&w, const  CDB::MODEL &m, const  xrLC_GlobalData  &lc_global_data )
{
	w.w_u32( (u32)m.get_verts_count() );
	w.w( m.get_verts(), m.get_verts_count() * sizeof(Fvector) );
	
	u32 tris_count = (u32) m.get_tris_count() ;
	w.w_u32( tris_count );
	for( u32 i = 0; i < tris_count; ++i)
		::write( w, m.get_tris()[i], lc_global_data );

//	w.w( m.get_tris(), m.get_tris_count() * sizeof(CDB::TRI) );
}
void write( IWriter	&w, const  CDB::MODEL &m )
{
	w.w_u32( (u32)m.get_verts_count() );
	w.w( m.get_verts(), m.get_verts_count() * sizeof(Fvector) );
	
	u32 tris_count = (u32) m.get_tris_count() ;
	w.w_u32( tris_count );
	for( u32 i = 0; i < tris_count; ++i)
		::write( w, m.get_tris()[i] );

//	w.w( m.get_tris(), m.get_tris_count() * sizeof(CDB::TRI) );
}
Exemple #3
0
void CLightShadows::render	()
{
	// Gain access to collision-DB
	CDB::MODEL*		DB		= g_pGameLevel->ObjectSpace.GetStaticModel();
	CDB::TRI*		TRIS	= DB->get_tris();
	Fvector*		VERTS	= DB->get_verts();

	int			slot_line	= S_rt_size/S_size;
	
	// Projection and xform
	float _43					=	Device.mProject._43;
	Device.mProject._43			-=	0.002f; 
	RCache.set_xform_world		(Fidentity);
	RCache.set_xform_project	(Device.mProject);
	Fvector	View				= Device.vCameraPosition;
	
	// Render shadows
	RCache.set_Shader			(sh_World);
	RCache.set_Geometry			(geom_World);
	int batch					= 0;
	u32 Offset					= 0;
	FVF::LIT* pv				= (FVF::LIT*) RCache.Vertex.Lock	(batch_size*3,geom_World->vb_stride,Offset);
	for (u32 s_it=0; s_it<shadows.size(); s_it++)
	{
		Device.Statistic->RenderDUMP_Srender.Begin	();
		shadow&		S			=	shadows[s_it];
		float		Le			=	S.L->color.intensity()*S.E;
		int			s_x			=	S.slot%slot_line;
		int			s_y			=	S.slot/slot_line;
		Fvector2	t_scale, t_offset;
		t_scale.set	(float(S_size)/float(S_rt_size),float(S_size)/float(S_rt_size));
		t_scale.mul (.5f);
		t_offset.set(float(s_x)/float(slot_line),float(s_y)/float(slot_line));
		t_offset.x	+= .5f/S_rt_size;
		t_offset.y	+= .5f/S_rt_size;
		
		// Search the cache
		cache_item*						CI		= 0; BOOL	bValid = FALSE;
		cache_item						CI_what; CI_what.O	= S.O; CI_what.L = S.L; CI_what.tris=0;
		xr_vector<cache_item>::iterator	CI_ptr	= std::lower_bound(cache.begin(),cache.end(),CI_what,cache_search);
		if (CI_ptr==cache.end())		
		{	// empty ?
			CI_ptr	= cache.insert		(CI_ptr,CI_what);
			CI		= &*CI_ptr;
			bValid	= FALSE;
		} else {
			if (CI_ptr->O != CI_what.O  || CI_ptr->L != CI_what.L)	
			{	// we found something different
				CI_ptr	= cache.insert		(CI_ptr,CI_what);
				CI		= &*CI_ptr;
				bValid	= FALSE;
			} else {
				// Everything, OK. Check if info is still relevant...
				CI		= &*CI_ptr;
				bValid	= TRUE;
				if (!CI->Op.similar(CI->O->renderable.xform.c))	bValid = FALSE;
				else if (!CI->Lp.similar(CI->L->position))		bValid = FALSE;
			}
		}
		CI->time				= Device.dwTimeGlobal;	// acess time

		if (!bValid)			{
			// Frustum
			CFrustum				F;
			F.CreateFromMatrix		(S.M,FRUSTUM_P_ALL);

			// Query
			xrc.frustum_options		(0);
			xrc.frustum_query		(DB,F);
			if (0==xrc.r_count())	continue;

			// Clip polys by frustum
			tess.clear				();
			for (CDB::RESULT* p = xrc.r_begin(); p!=xrc.r_end(); p++)
			{
				VERIFY((p->id>=0)&&(p->id<DB->get_tris_count()));
				// 
				CDB::TRI&	t		= TRIS[p->id];
				if (t.suppress_shadows) continue;
				sPoly		A,B;
				A.push_back			(VERTS[t.verts[0]]);
				A.push_back			(VERTS[t.verts[1]]);
				A.push_back			(VERTS[t.verts[2]]);

				// Calc plane, throw away degenerate tris and invisible to light polygons
				Fplane				P;	float mag = 0;
				Fvector				t1,t2,n;
				t1.sub				(A[0],A[1]);
				t2.sub				(A[0],A[2]);
				n.crossproduct		(t1,t2);
				mag	= n.square_magnitude();
				if (mag<EPS_S)						continue;
				n.mul				(1.f/_sqrt(mag));
				P.build_unit_normal	(A[0],n);
				float	DOT_Fade	= P.classify(S.L->position);
				if (DOT_Fade<0)		continue;

				// Clip polygon
				sPoly*		clip	= F.ClipPoly	(A,B);
				if (0==clip)		continue;

				// Triangulate poly 
				for (u32 v=2; v<clip->size(); v++)	{
					tess.push_back	(tess_tri());
					tess_tri& T		= tess.back();
					T.v[0]			= (*clip)[0];
					T.v[1]			= (*clip)[v-1];
					T.v[2]			= (*clip)[v];
					T.N				= P.n;
				}
			}

			// Remember params which builded cache item
			CI->O					= S.O;
			CI->Op					= CI->O->renderable.xform.c;
			CI->L					= S.L;
			CI->Lp					= CI->L->position;
			CI->tcnt				= tess.size();
			//Msg						("---free--- %x",u32(CI->tris));
			xr_free					(CI->tris);	VERIFY(0==CI->tris);	
			if (tess.size())		{
				CI->tris			= xr_alloc<tess_tri>(CI->tcnt);
				//Msg					("---alloc--- %x",u32(CI->tris));
				CopyMemory		(CI->tris,&*tess.begin(),CI->tcnt * sizeof(tess_tri));
			}
		}

		// Fill VB
		for (u32 tid=0; tid<CI->tcnt; tid++)	{
			tess_tri&	TT		= CI->tris[tid];
			Fvector* 	v		= TT.v;
			Fvector		T;
			Fplane		ttp;	ttp.build_unit_normal(v[0],TT.N);

			if (ttp.classify(View)<0)						continue;
			int	c0		= PLC_calc(v[0],TT.N,S.L,Le,S.C);
			int	c1		= PLC_calc(v[1],TT.N,S.L,Le,S.C);
			int	c2		= PLC_calc(v[2],TT.N,S.L,Le,S.C);
			if (c0>S_clip && c1>S_clip && c2>S_clip)		continue;	
			clamp		(c0,S_ambient,255);
			clamp		(c1,S_ambient,255);
			clamp		(c2,S_ambient,255);

			S.M.transform(T,v[0]); pv->set(v[0],CLS(c0),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++;
			S.M.transform(T,v[1]); pv->set(v[1],CLS(c1),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++;
			S.M.transform(T,v[2]); pv->set(v[2],CLS(c2),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++;

			batch++;
			if (batch==batch_size)	{
				// Flush
				RCache.Vertex.Unlock	(batch*3,geom_World->vb_stride);
				RCache.Render			(D3DPT_TRIANGLELIST,Offset,batch);

				pv						= (FVF::LIT*) RCache.Vertex.Lock(batch_size*3,geom_World->vb_stride,Offset);
				batch					= 0;
			}
		}
		Device.Statistic->RenderDUMP_Srender.End	();
	}

	// Flush if nessesary
	RCache.Vertex.Unlock	(batch*3,geom_World->vb_stride);
	if (batch)				{
		RCache.Render			(D3DPT_TRIANGLELIST,Offset,batch);
	}
	
	// Clear all shadows and free old entries in the cache
	shadows.clear				();
	for (int cit=0; cit<int(cache.size()); cit++)	{
		cache_item&		ci		= cache[cit];
		u32				time	= Device.dwTimeGlobal - ci.time;
		if				(time > cache_old)	{
			//Msg			("---free--- %x",u32(ci.tris));
			xr_free		(ci.tris);	VERIFY(0==ci.tris);
			cache.erase (cache.begin()+cit);
			cit			--;
		}
	}

	// Projection
	Device.mProject._43			= _43;
	RCache.set_xform_project	(Device.mProject);
}