Ejemplo n.º 1
0
	void			_prim		(DWORD prim)
	{
		if (bClass3)	{
			sPoly		src,dst;
			src.resize	(3);
			src[0]		= verts[ tris[prim].verts[0] ];
			src[1]		= verts[ tris[prim].verts[1] ];
			src[2]		= verts[ tris[prim].verts[2] ];
			if (F->ClipPoly(src,dst))
			{
				RESULT& R	= dest->r_add();
				R.id		= prim;
				R.verts[0]	= verts[ tris[prim].verts[0] ];
				R.verts[1]	= verts[ tris[prim].verts[1] ];
				R.verts[2]	= verts[ tris[prim].verts[2] ];
				R.dummy		= tris[prim].dummy;
			}
		} else {
			RESULT& R	= dest->r_add();
			R.id		= prim;
			R.verts[0]	= verts[ tris[prim].verts[0] ];
			R.verts[1]	= verts[ tris[prim].verts[1] ];
			R.verts[2]	= verts[ tris[prim].verts[2] ];
			R.dummy		= tris[prim].dummy;
		}
	}
Ejemplo n.º 2
0
void EDetailManager::UpdateSlotBBox(int sx, int sz, DetailSlot& slot)
{
	Fbox bbox;
    Frect rect;
    GetSlotRect			(rect,sx,sz);
    bbox.min.set		(rect.x1, m_BBox.min.y, rect.y1);
    bbox.max.set		(rect.x2, m_BBox.max.y, rect.y2);

    SBoxPickInfoVec pinf;
    ETOOLS::box_options(0);
    if (Scene->BoxPickObjects(bbox,pinf,&m_SnapObjects)){
		bbox.grow		(EPS_L_VAR);
    	Fplane			frustum_planes[4];
		frustum_planes[0].build(bbox.min,left_vec);
		frustum_planes[1].build(bbox.min,back_vec);
		frustum_planes[2].build(bbox.max,right_vec);
		frustum_planes[3].build(bbox.max,fwd_vec);

        CFrustum frustum;
        frustum.CreateFromPlanes(frustum_planes,4);

        float y_min		= flt_max;
        float y_max		= flt_min;
		for (SBoxPickInfoIt it=pinf.begin(); it!=pinf.end(); it++){
        	for (int k=0; k<(int)it->inf.size(); k++){
                float range;
                Fvector verts[3];
                it->e_obj->GetFaceWorld(it->s_obj->_Transform(),it->e_mesh,it->inf[k].id,verts);
                sPoly sSrc	(verts,3);
                sPoly sDest;
                sPoly* sRes = frustum.ClipPoly(sSrc, sDest);
                if (sRes){
                    for (u32 k=0; k<sRes->size(); k++){
                        float H = (*sRes)[k].y;
                        if (H>y_max) y_max = H+0.03f;
                        if (H<y_min) y_min = H-0.03f;
                    }
                    slot.w_y	(y_min,y_max-y_min);
                    slot.w_id(0,DetailSlot::ID_Empty);
                    slot.w_id(1,DetailSlot::ID_Empty);
                    slot.w_id(2,DetailSlot::ID_Empty);
                    slot.w_id(3,DetailSlot::ID_Empty);
                }
            }
	    }
    }else{
    	ZeroMemory(&slot,sizeof(DetailSlot));
    	slot.w_id(0,DetailSlot::ID_Empty);
    	slot.w_id(1,DetailSlot::ID_Empty);
    	slot.w_id(2,DetailSlot::ID_Empty);
    	slot.w_id(3,DetailSlot::ID_Empty);
    }
}
Ejemplo n.º 3
0
BOOL CFrustum::CreateFromClipPoly(Fvector* p, int count, Fvector& vBase, CFrustum& clip)
{
	VERIFY(count<FRUSTUM_MAXPLANES);
	VERIFY(count>=3);

	sPoly	poly1	(p,count);
	sPoly	poly2;
	sPoly*	dest	= clip.ClipPoly(poly1,poly2);

	// here we end up with complete frustum-polygon in 'dest'
	if (0==dest)	return false;

	CreateFromPoints(dest->begin(),dest->size(),vBase);
	return	true;
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
void CSector::traverse			(CFrustum &F, _scissor& R_scissor)
{
	// Register traversal process
	if (r_marker	!=	PortalTraverser.i_marker)	{
		r_marker							=	PortalTraverser.i_marker;
		PortalTraverser.r_sectors.push_back	(this);
		r_frustums.clear					();
		r_scissors.clear					();
	}
	r_frustums.push_back		(F);
	r_scissors.push_back		(R_scissor);

	// Search visible portals and go through them
	sPoly	S,D;
	for	(u32 I=0; I<m_portals.size(); I++)
	{
		if (m_portals[I]->marker == PortalTraverser.i_marker) continue;

		CPortal* PORTAL = m_portals[I];
		CSector* pSector;

		// Select sector (allow intersecting portals to be finely classified)
		if (PORTAL->bDualRender) {
			pSector = PORTAL->getSector						(this);
		} else {
			pSector = PORTAL->getSectorBack					(PortalTraverser.i_vBase);
			if (pSector==this)								continue;
			if (pSector==PortalTraverser.i_start)			continue;
		}

		// Early-out sphere
		if (!F.testSphere_dirty(PORTAL->S.P,PORTAL->S.R))	continue;

		// SSA	(if required)
		if (PortalTraverser.i_options&CPortalTraverser::VQ_SSA)
		{
			Fvector				dir2portal;
			dir2portal.sub		(PORTAL->S.P,	PortalTraverser.i_vBase);
			float R				=	PORTAL->S.R	;
			float distSQ		=	dir2portal.square_magnitude();
			float ssa			=	R*R/distSQ;
			dir2portal.div		(_sqrt(distSQ));
			ssa					*=	_abs(PORTAL->P.n.dotproduct(dir2portal));
			if (ssa<r_ssaDISCARD)	continue;

			if (PortalTraverser.i_options&CPortalTraverser::VQ_FADE)	{
				if (ssa<r_ssaLOD_A)	PortalTraverser.fade_portal			(PORTAL,ssa);
				if (ssa<r_ssaLOD_B)	continue							;
			}
		}

		// Clip by frustum
		svector<Fvector,8>&	POLY = PORTAL->getPoly();
		S.assign			(&*POLY.begin(),POLY.size()); D.clear();
		sPoly* P			= F.ClipPoly(S,D);
		if (0==P)			continue;

		// Scissor and optimized HOM-testing
		_scissor			scissor	;
		if (PortalTraverser.i_options&CPortalTraverser::VQ_SCISSOR && (!PORTAL->bDualRender))
		{
			// Build scissor rectangle in projection-space
			Fbox2	bb;	bb.invalidate(); float depth = flt_max;
			sPoly&	p	= *P;
			for		(u32 vit=0; vit<p.size(); vit++)	{
				Fvector4	t;	
				Fmatrix&	M	= PortalTraverser.i_mXFORM_01;
				Fvector&	v	= p[vit];

				t.x = v.x*M._11 + v.y*M._21 + v.z*M._31 + M._41;
				t.y = v.x*M._12 + v.y*M._22 + v.z*M._32 + M._42;
				t.z = v.x*M._13 + v.y*M._23 + v.z*M._33 + M._43;
				t.w = v.x*M._14 + v.y*M._24 + v.z*M._34 + M._44;
				t.mul	(1.f/t.w);

				if (t.x < bb.min.x)	bb.min.x	= t.x; 
				if (t.x > bb.max.x) bb.max.x	= t.x;
				if (t.y < bb.min.y)	bb.min.y	= t.y; 
				if (t.y > bb.max.y) bb.max.y	= t.y;
				if (t.z < depth)	depth		= t.z;
			}
			// Msg	("bb(%s): (%f,%f)-(%f,%f), d=%f", PORTAL->bDualRender?"true":"false",bb.min.x, bb.min.y, bb.max.x, bb.max.y,depth);
			if (depth<EPS)	{
				scissor	= R_scissor;

				// Cull by HOM (slower algo)
				if  (
					(PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && 
					(!RImplementation.HOM.visible(*P))
					)	continue;
			} else {
				// perform intersection (this is just to be sure, it is probably clipped in 3D already)
				if (bb.min.x > R_scissor.min.x)	scissor.min.x = bb.min.x; else scissor.min.x = R_scissor.min.x;
				if (bb.min.y > R_scissor.min.y)	scissor.min.y = bb.min.y; else scissor.min.y = R_scissor.min.y;
				if (bb.max.x < R_scissor.max.x) scissor.max.x = bb.max.x; else scissor.max.x = R_scissor.max.x;
				if (bb.max.y < R_scissor.max.y) scissor.max.y = bb.max.y; else scissor.max.y = R_scissor.max.y;
				scissor.depth	= depth;

				// Msg	("scissor: (%f,%f)-(%f,%f)", scissor.min.x, scissor.min.y, scissor.max.x, scissor.max.y);
				// Check if box is non-empty
				if (scissor.min.x >= scissor.max.x)	continue;
				if (scissor.min.y >= scissor.max.y)	continue;

				// Cull by HOM (faster algo)
				if  (
					(PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && 
					(!RImplementation.HOM.visible(scissor,depth))
					)	continue;
			}
		} else {
			scissor	= R_scissor;

			// Cull by HOM (slower algo)
			if  (
				(PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && 
				(!RImplementation.HOM.visible(*P))
				)	continue;
		}

		// Create _new_ frustum and recurse
		CFrustum				Clip;
		Clip.CreateFromPortal	(P, PORTAL->P.n, PortalTraverser.i_vBase,PortalTraverser.i_mXFORM);
		PORTAL->marker			= PortalTraverser.i_marker;
		PORTAL->bDualRender		= FALSE;
		pSector->traverse		(Clip,scissor);
	}
}
Ejemplo n.º 6
0
void CHOM::Render_DB			(CFrustum& base)
{
	//Update projection matrices on every frame to ensure valid HOM culling
	float			view_dim	= occ_dim_0;
	Fmatrix			m_viewport		= {
		view_dim/2.f,			0.0f,					0.0f,		0.0f,
		0.0f,					-view_dim/2.f,			0.0f,		0.0f,
		0.0f,					0.0f,					1.0f,		0.0f,
		view_dim/2.f + 0 + 0,	view_dim/2.f + 0 + 0,	0.0f,		1.0f
	};
	Fmatrix			m_viewport_01	= {
		1.f/2.f,			0.0f,				0.0f,		0.0f,
		0.0f,				-1.f/2.f,			0.0f,		0.0f,
		0.0f,				0.0f,				1.0f,		0.0f,
		1.f/2.f + 0 + 0,	1.f/2.f + 0 + 0,	0.0f,		1.0f
	};
	m_xform.mul					(m_viewport,	Device.mFullTransform);
	m_xform_01.mul				(m_viewport_01,	Device.mFullTransform);

	// Query DB
	xrc.frustum_options			(0);
	xrc.frustum_query			(m_pModel,base);
	if (0==xrc.r_count())		return;

	// Prepare
	CDB::RESULT*	it			= xrc.r_begin	();
	CDB::RESULT*	end			= xrc.r_end		();
	
	Fvector			COP			= Device.vCameraPosition;
	end				= std::remove_if	(it,end,pred_fb(m_pTris));
	std::sort		(it,end,pred_fb(m_pTris,COP));

	// Build frustum with near plane only
	CFrustum					clip;
	clip.CreateFromMatrix		(Device.mFullTransform,FRUSTUM_P_NEAR);
	sPoly						src,dst;
	u32		_frame				= Device.dwFrame	;
#ifdef DEBUG
	tris_in_frame				= xrc.r_count();
	tris_in_frame_visible		= 0;
#endif

	// Perfrom selection, sorting, culling
	for (; it!=end; it++)
	{
		// Control skipping
		occTri& T			= m_pTris	[it->id];
		u32	next			= _frame + ::Random.randI(3,10);

		// Test for good occluder - should be improved :)
		if (!(T.flags || (T.plane.classify(COP)>0)))	
		{ T.skip=next; continue; }

		// Access to triangle vertices
		CDB::TRI& t		= m_pModel->get_tris()	[it->id];
		Fvector*  v		= m_pModel->get_verts();
		src.clear		();	dst.clear	();
		src.push_back	(v[t.verts[0]]);
		src.push_back	(v[t.verts[1]]);
		src.push_back	(v[t.verts[2]]);
		sPoly* P =		clip.ClipPoly	(src,dst);
		if (0==P)		{ T.skip=next; continue; }

		// XForm and Rasterize
#ifdef DEBUG
		tris_in_frame_visible	++;
#endif
		u32		pixels			= 0;
		int		limit			= int(P->size())-1;
		for (int v=1; v<limit; v++)	{
			m_xform.transform	(T.raster[0],(*P)[0]);
			m_xform.transform	(T.raster[1],(*P)[v+0]);
			m_xform.transform	(T.raster[2],(*P)[v+1]);
			pixels	+=			Raster.rasterize(&T);
		}
		if (0==pixels)	{ T.skip=next; continue; }
	}
}