예제 #1
0
void modify							(const int &vertex_id, Fbox &bounding_box)
{
	const CGameGraph		&graph = ai().game_graph();
	bounding_box.modify		(graph.vertex(vertex_id)->game_point());

	CGameGraph::const_iterator	I,E;
	graph.begin				(vertex_id,I,E);
	for ( ; I != E; ++I)
		bounding_box.modify	(graph.vertex(graph.value(vertex_id,I))->game_point());
}
예제 #2
0
void ESceneAIMapTool::GetBBox(Fbox& bb, bool bSelOnly)
{
    switch (LTools->GetSubTarget()){
    case estAIMapNode:{
    	if (bSelOnly){
            for (AINodeIt it=m_Nodes.begin(); it!=m_Nodes.end(); it++)
                if ((*it)->flags.is(SAINode::flSelected)){
                	bb.modify(Fvector().add((*it)->Pos,-m_Params.fPatchSize*0.5f));
                	bb.modify(Fvector().add((*it)->Pos,m_Params.fPatchSize*0.5f));
                }
        }else{
        	bb.merge		(m_AIBBox);
        }
    }break;
    }
}
예제 #3
0
void ESceneAIMapTool::CalculateNodesBBox(Fbox& bb)
{
    bb.invalidate();
	for (AINodeIt b_it=m_Nodes.begin(); b_it!=m_Nodes.end(); ++b_it)
    {
    	VERIFY(_valid((*b_it)->Pos));
    	bb.modify((*b_it)->Pos);
    }
}
예제 #4
0
IC void get_q_box( Fbox &xf,  float c, float alpha, float radius )
{
	Fvector src_pt,		tgt_pt;
	calc_point			(tgt_pt,radius,0,alpha);
	src_pt.set			(0,tgt_pt.y,0);
	xf.invalidate		();
	xf.modify			(src_pt);
	xf.modify			(tgt_pt);
	xf.grow				(c);

}
예제 #5
0
float	CalculateHeight(Fbox& BB)
{
	// All nodes
	BB.invalidate();

	for (u32 i=0; i<g_nodes.size(); i++)
	{
		vertex&	N	= g_nodes[i];
		BB.modify	(N.Pos);
	}
	return BB.max.y-BB.min.y+EPS_L;
}
예제 #6
0
void ComputeSphere(Fsphere &B, FvectorVec& V)
{
    if (V.size()<3) 	{ B.P.set(0,0,0); B.R=0.f; return; }

	// 1: calc first variation
	Fsphere	S1;
    Fsphere_compute		(S1,V.begin(),V.size());
	BOOL B1				= SphereValid(V,S1);
    
	// 2: calc ordinary algorithm (2nd)
	Fsphere	S2;
	Fbox bbox;
    bbox.invalidate		();
	for (FvectorIt I=V.begin(); I!=V.end(); I++)	bbox.modify(*I);
	bbox.grow			(EPS_L);
	bbox.getsphere		(S2.P,S2.R);
	S2.R = -1;
	for (I=V.begin(); I!=V.end(); I++)	{
		float d = S2.P.distance_to_sqr(*I);
		if (d>S2.R) S2.R=d;
	}
	S2.R = _sqrt (_abs(S2.R));
	BOOL B2				= SphereValid(V,S2);

	// 3: calc magic-fm
	Mgc::Sphere _S3 = Mgc::MinSphere(V.size(), (const Mgc::Vector3*) V.begin());
	Fsphere	S3;
	S3.P.set			(_S3.Center().x,_S3.Center().y,_S3.Center().z);
	S3.R				= _S3.Radius();
	BOOL B3				= SphereValid(V,S3);

	// select best one
	if (B1 && (S1.R<S2.R)){		// miniball or FM
		if (B3 && (S3.R<S1.R)){ // FM wins
        	B.set	(S3);
		}else{					// MiniBall wins
        	B.set	(S1);
		}
	}else{						// base or FM
		if (B3 && (S3.R<S2.R)){	// FM wins
        	B.set	(S3);
		}else{					// Base wins :)
        	R_ASSERT(B2);
        	B.set	(S2);
		}
	}
}
void xrMU_Model::calc_lighting	()
{
	// BB
	Fbox			BB; 
	BB.invalidate	();
	for (v_vertices_it vit=m_vertices.begin(); vit!=m_vertices.end(); vit++)
		BB.modify	((*vit)->P);

	// Export CForm
	CDB::CollectorPacked	CL	(BB,(u32)m_vertices.size(),(u32)m_faces.size());
	export_cform_rcast		(CL,Fidentity);

	CDB::MODEL*				M	= xr_new<CDB::MODEL>	();
	M->build				(CL.getV(),(u32)CL.getVS(),CL.getT(),(u32)CL.getTS());

	calc_lighting			(color,Fidentity,M,inlc_global_data()->L_static(),LP_dont_rgb+LP_dont_sun);

	xr_delete				(M);

	clMsg					("model '%s' - REF_lighted.",*m_name);
}
예제 #8
0
bool CGroupObject::GetBox(Fbox& bb)
{
    bb.invalidate		();
    // update box
    for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){
        switch((*it)->ClassID){
        case OBJCLASS_SPAWNPOINT:
        case OBJCLASS_SCENEOBJECT:{
            Fbox 	box;
            if ((*it)->GetBox(box))
                bb.merge(box);
        }break;
        default:
            bb.modify((*it)->PPosition);
        }
    }
    if (!bb.is_valid()){
    	bb.set			(PPosition,PPosition);
        bb.grow			(EMPTY_GROUP_SIZE);
    }
    return bb.is_valid();
}
예제 #9
0
파일: r__sector.cpp 프로젝트: 2asoft/xray
void	CPortal::Setup	(Fvector* V, int vcnt, CSector* face, CSector* back)
{
	// calc sphere
	Fbox				BB;
	BB.invalidate		();
	for (int v=0; v<vcnt; v++)
		BB.modify		(V[v]);
	BB.getsphere		(S.P,S.R);

	// 
	poly.assign			(V,vcnt);
	pFace				= face; 
	pBack				= back;
	marker				= 0xffffffff; 

	Fvector				N,T;
	N.set				(0,0,0);

	FPU::m64r();
	u32	_cnt			= 0;
	for (int i=2; i<vcnt; i++) {
		T.mknormal_non_normalized		(poly[0],poly[i-1],poly[i]);
		float		m	= T.magnitude	();
		if (m>EPS_S)	{
			N.add		(T.div(m))	;
			_cnt		++			;
		}
	}
	R_ASSERT2	(_cnt, "Invalid portal detected");
	N.div		(float(_cnt));
	P.build		(poly[0],N);
	FPU::m24r	();

	/*
	if (_abs(1-P.n.magnitude())<EPS)
	xrDebug::Fatal		(DEBUG_INFO,"Degenerated portal found at {%3.2f,%3.2f,%3.2f}.",VPUSH(poly[0]));
	*/
}
예제 #10
0
void CWallmarksEngine::AddWallmark_internal	(CDB::TRI* pTri, const Fvector* pVerts, const Fvector &contact_point, ref_shader hShader, float sz)
{
	// query for polygons in bounding box
	// calculate adjacency
	{
		Fbox				bb_query;
		Fvector				bbc,bbd;
		bb_query.set		(contact_point,contact_point);
		bb_query.grow		(sz*2.5f);
		bb_query.get_CD		(bbc,bbd);
		xrc.box_options		(CDB::OPT_FULL_TEST);
		xrc.box_query		(g_pGameLevel->ObjectSpace.GetStaticModel(),bbc,bbd);
		u32	triCount		= xrc.r_count	();
		if (0==triCount)	return;
		CDB::TRI* tris		= g_pGameLevel->ObjectSpace.GetStaticTris();
		sml_collector.clear	();
		sml_collector.add_face_packed_D	(pVerts[pTri->verts[0]],pVerts[pTri->verts[1]],pVerts[pTri->verts[2]],0);
		for (u32 t=0; t<triCount; t++)	{
			CDB::TRI*	T	= tris+xrc.r_begin()[t].id;
			if (T==pTri)	continue;
			sml_collector.add_face_packed_D		(pVerts[T->verts[0]],pVerts[T->verts[1]],pVerts[T->verts[2]],0);
		}
		sml_collector.calc_adjacency	(sml_adjacency);
	}

	// calc face normal
	Fvector	N;
	N.mknormal			(pVerts[pTri->verts[0]],pVerts[pTri->verts[1]],pVerts[pTri->verts[2]]);
	sml_normal.set		(N);

	// build 3D ortho-frustum
	Fmatrix				mView,mRot;
	BuildMatrix			(mView,1/sz,contact_point);
	mRot.rotateZ		(::Random.randF(deg2rad(-20.f),deg2rad(20.f)));
	mView.mulA_43		(mRot);
	sml_clipper.CreateFromMatrix	(mView,FRUSTUM_P_LRTB);

	// create wallmark
	static_wallmark* W	= static_wm_allocate();
	RecurseTri			(0,mView,*W);

	// calc sphere
	if (W->verts.size()<3) { static_wm_destroy(W); return; }
	else {
		Fbox bb;	bb.invalidate();

		FVF::LIT* I=&*W->verts.begin	();
		FVF::LIT* E=&*W->verts.end		();
		for (; I!=E; I++)	bb.modify	(I->p);
		bb.getsphere					(W->bounds.P,W->bounds.R);
	}

	if (W->bounds.R < 1.f)	
	{
		// search if similar wallmark exists
		wm_slot* slot			= FindSlot	(hShader);
		if (slot){
			StaticWMVecIt it	=	slot->static_items.begin	();
			StaticWMVecIt end	=	slot->static_items.end	();
			for (; it!=end; it++)	{
				static_wallmark* wm		=	*it;
				if (wm->bounds.P.similar(W->bounds.P,0.02f)){ // replace
					static_wm_destroy	(wm);
					*it					=	W;
					return;
				}
			}
		} else {
			slot		= AppendSlot(hShader);
		}

		// no similar - register _new_
		slot->static_items.push_back(W);
	}
}
예제 #11
0
void CBuild::xrPhase_Subdivide()
{
	Status	("Subdividing in space...");
	vecFace s1, s2;
	Fbox	b1, b2;
	for (int X=0; X<int(g_XSplit.size()); X++)
	{
		if (g_XSplit[X]->empty()) 
		{
			xr_delete		(g_XSplit[X]);
			g_XSplit.erase	(g_XSplit.begin()+X);
			X--;
			continue;
		}
		Progress			(float(X)/float(g_XSplit.size()));
		
		// skip if subdivision is too small already
		if (int(g_XSplit[X]->size())<(c_SS_LowVertLimit*2))	continue;
		
		// calc bounding box
		Fbox	bb;
		Fvector size;
		
		bb.invalidate();
		for (vecFaceIt F=g_XSplit[X]->begin(); F!=g_XSplit[X]->end(); F++) 
		{
			Face *XF = *F;
			bb.modify(XF->v[0]->P);
			bb.modify(XF->v[1]->P);
			bb.modify(XF->v[2]->P);
		}
		
		// analyze if we need to split
		size.sub(bb.max,bb.min);
		BOOL	bSplit	= FALSE;
		if  	(size.x>c_SS_maxsize)					bSplit	= TRUE;
		if		(size.y>c_SS_maxsize)					bSplit	= TRUE;
		if		(size.z>c_SS_maxsize)					bSplit	= TRUE;
		if		(int(g_XSplit[X]->size()) > c_SS_HighVertLimit)	bSplit	= TRUE;
		CDeflector*	defl_base	= (CDeflector*)g_XSplit[X]->front()->pDeflector;
		if		(!bSplit && defl_base)	{
			if (defl_base->layer.width  >=	(c_LMAP_size-2*BORDER))	bSplit	= TRUE;
			if (defl_base->layer.height >=	(c_LMAP_size-2*BORDER))	bSplit	= TRUE;
		}

		// perform subdivide if needed
		if (!bSplit)	continue;
		
		// select longest BBox edge
		int		box_edge			= -1;	
		if (size.x>=size.y && size.x>=size.z) {
			box_edge	= 0;
		} else {
			if (size.y>=size.x && size.y>=size.z) {
				box_edge	= 1;
			} else {
				box_edge	= 2;
			}
		}
		setup_bbs	(b1,b2,bb,box_edge);

		// align plane onto vertices
		
		// Process all faces and rearrange them
		u32		iteration_on_edge	= 0	;	// up to 3
		u32		iteration_per_edge	= 0	;	// up to 10
resplit:
		s2.clear	();
		s1.clear	();
		iteration_per_edge		++	;
		for (vecFaceIt F=g_XSplit[X]->begin(); F!=g_XSplit[X]->end(); F++) 
		{
			Face *XF = *F;
			Fvector C;
			XF->CalcCenter(C);
			if (b1.contains(C))	{ s1.push_back(XF); }
			else				{ s2.push_back(XF); }
		}
		
		if ((int(s1.size())<c_SS_LowVertLimit) || (int(s2.size())<c_SS_LowVertLimit))
		{
			// splitting failed
			clMsg	("! ERROR: model #%d - split fail, faces: %d, s1/s2:%d/%d",X,g_XSplit[X]->size(),s1.size(),s2.size());
			if (iteration_per_edge<10)	{
				if		(g_XSplit[X]->size() > c_SS_LowVertLimit*4)		
				{
					if (s2.size()>s1.size())	
					{	//b2 -less, b1-grow
						size.sub	(b2.max,b2.min);
						b1.max[box_edge]	+= size[box_edge]/2;
						b2.min[box_edge]	=  b1.max[box_edge];
					} else {
						//b2 -grow, b1-less
						size.sub	(b1.max,b1.min);
						b2.min[box_edge]	-= size[box_edge]/2;
						b1.max[box_edge]	=  b2.min[box_edge];
					}
					goto		resplit;
				}
			} else {
				// switch edge
				iteration_per_edge	= 0	;
				iteration_on_edge	++	;
				if (iteration_on_edge<3)	{
					box_edge		= (box_edge+1)%3;
					setup_bbs		(b1,b2,bb,box_edge);
					goto		resplit;
				}
			}
		} else {
			// split deflector into TWO
			if (defl_base)	
			{
				// _delete old deflector
				for (u32 it=0; it<lc_global_data()->g_deflectors().size(); it++)
				{
					if (lc_global_data()->g_deflectors()[it]==defl_base)	{
						lc_global_data()->g_deflectors().erase	(lc_global_data()->g_deflectors().begin()+it);
						xr_delete			(defl_base);
						break;
					}
				}
				
				// Create _new deflectors
				CDeflector*		D1	= new CDeflector(); D1->OA_Place(s1); D1->OA_Export(); lc_global_data()->g_deflectors().push_back(D1);
				CDeflector*		D2	= new CDeflector(); D2->OA_Place(s2); D2->OA_Export(); lc_global_data()->g_deflectors().push_back(D2);
			}
			
			// Delete old SPLIT and push two new
			xr_delete				(g_XSplit[X]);
			g_XSplit.erase			(g_XSplit.begin()+X); X--;
			g_XSplit.push_back		(new vecFace(s1));	Detach(&s1);
			g_XSplit.push_back		(new vecFace(s2));	Detach(&s2);
		}
		s1.clear	();
		s2.clear	();
	}
	clMsg("%d subdivisions.",g_XSplit.size());
	validate_splits	();
}
예제 #12
0
void GetBox( Fbox& box, const Fvector *verts, u32 cnt )
{
    box.invalidate();
	for( u32 i = 0; i < cnt; ++i )
    	box.modify( verts[i] );  
}
예제 #13
0
void CBuild::BuildCForm	()
{
	// Collecting data
	Phase		("CFORM: creating...");
	vecFace*	cfFaces		= new vecFace();
	vecVertex*	cfVertices	= new vecVertex();
	{
		xr_vector<bool>			cfVertexMarks;
		cfVertexMarks.assign	(lc_global_data()->g_vertices().size(),false);

		Status("Sorting...");
		std::sort(lc_global_data()->g_vertices().begin(),lc_global_data()->g_vertices().end());

		Status("Collecting faces...");
		cfFaces->reserve	(lc_global_data()->g_faces().size());
		for (vecFaceIt I=lc_global_data()->g_faces().begin(); I!=lc_global_data()->g_faces().end(); ++I)
		{
			Face* F = *I;
			if (F->Shader().flags.bCollision) 
			{
				cfFaces->push_back(F);
				int index = GetVertexIndex(F->v[0]);
				cfVertexMarks[index] = true;

				index = GetVertexIndex(F->v[1]);
				cfVertexMarks[index] = true;

				index = GetVertexIndex(F->v[2]);
				cfVertexMarks[index] = true;
			}
		}

		Status("Collecting vertices...");
		cfVertices->reserve	(lc_global_data()->g_vertices().size());
		std::sort(cfFaces->begin(),cfFaces->end());
		for (u32 V=0; V<lc_global_data()->g_vertices().size(); V++)
			if (cfVertexMarks[V]) cfVertices->push_back(lc_global_data()->g_vertices()[V]);
	}

	float	p_total = 0;
	float	p_cost  = 1.f/(cfVertices->size());
	
	Fbox BB; BB.invalidate();
	for (vecVertexIt it = cfVertices->begin(); it!=cfVertices->end(); it++)
		BB.modify((*it)->P );

	// CForm
	Phase	("CFORM: collision model...");
	Status	("Items to process: %d", cfFaces->size());
	p_total = 0;
	p_cost  = 1.f/(cfFaces->size());

	// Collect faces
	CDB::CollectorPacked CL	(BB,cfVertices->size(),cfFaces->size());
	for (vecFaceIt F = cfFaces->begin(); F!=cfFaces->end(); F++)
	{
		Face*	T = *F;

		TestEdge	(T->v[0],T->v[1],T);
		TestEdge	(T->v[1],T->v[2],T);
		TestEdge	(T->v[2],T->v[0],T);

		CL.add_face	(
			T->v[0]->P, T->v[1]->P, T->v[2]->P,
			T->dwMaterialGame, materials()[T->dwMaterial].sector, T->sm_group
			);
		Progress(p_total+=p_cost);		// progress
	}
	if (bCriticalErrCnt) {
		err_save	();
		clMsg		("MultipleEdges: %d faces",bCriticalErrCnt);
	}
	xr_delete		(cfFaces);
	xr_delete		(cfVertices);

	// Models
	Status			("Models...");
	for (u32 ref=0; ref<mu_refs().size(); ref++)
		mu_refs()[ref]->export_cform_game(CL);

	// Simplification
	if (g_params().m_quality!=ebqDraft)
		SimplifyCFORM	(CL);

	// bb?
	BB.invalidate	();
	for (size_t it = 0; it<CL.getVS(); it++)
		BB.modify( CL.getV()[it] );

	// Saving
	string_path		fn;
	IWriter*		MFS	= FS.w_open	(strconcat(sizeof(fn),fn,pBuild->path,"level.cform"));
	Status			("Saving...");

	// Header
	hdrCFORM hdr;
	hdr.version		= CFORM_CURRENT_VERSION;
	hdr.vertcount	= (u32)CL.getVS();
	hdr.facecount	= (u32)CL.getTS();
	hdr.aabb		= BB;
	MFS->w			(&hdr,sizeof(hdr));

	// Data
	MFS->w			(CL.getV(),(u32)CL.getVS()*sizeof(Fvector));
	MFS->w			(CL.getT(),(u32)CL.getTS()*sizeof(CDB::TRI));

	// Clear pDeflector (it is stored in the same memory space with dwMaterialGame)
	for (vecFaceIt I=lc_global_data()->g_faces().begin(); I!=lc_global_data()->g_faces().end(); I++)
	{
		Face* F			= *I;
		F->pDeflector	= NULL;
	}

	FS.w_close		(MFS);
}
void	xrMU_Model::export_geometry		()
{
    // Declarator
    VDeclarator			D;
    D.set				(decl);

    // RT-check, BOX, low-point, frac-size
    Fbox			BB;
    BB.invalidate	();
    for (v_vertices_it vit=m_vertices.begin(); vit!=m_vertices.end(); vit++)
        BB.modify	((*vit)->P);

    Fvector			frac_low;
    float			frac_Ysize;
    BB.getcenter	(frac_low);
    frac_low.y	= BB.min.y;
    frac_Ysize		= BB.max.y - BB.min.y;

    // Begin building
    for (v_subdivs_it it=m_subdivs.begin(); it!=m_subdivs.end(); it++)
    {
        // Vertices
        {
            g_VB.Begin		(D);

            vecOGF_V&	verts	= it->ogf->vertices;
            for (u32 v_it=0; v_it<verts.size(); v_it++)
            {
                OGF_Vertex&		oV	= verts[v_it];

                // Position
                g_VB.Add	(&oV.P,3*sizeof(float));

                // Normal
                {
                    base_color_c	oV_c;
                    oV.Color._get(oV_c);
                    Fvector N	= oV.N;
                    N.add		(1.f);
                    N.mul		(.5f*255.f);
                    s32 nx		= iFloor(N.x);
                    clamp(nx,0,255);
                    s32 ny		= iFloor(N.y);
                    clamp(ny,0,255);
                    s32 nz		= iFloor(N.z);
                    clamp(nz,0,255);
                    s32 cc		= iFloor(oV_c.hemi*255.f);
                    clamp(cc,0,255);
                    u32	uN		= color_rgba(nx,ny,nz,cc);
                    g_VB.Add	(&uN,4);
                }

                // Tangent
                {
                    u32	uT		= color_rgba(oV.T.x,oV.T.y,oV.T.z,0);
                    g_VB.Add	(&uT,4);
                }

                // Binormal
                {
                    u32	uB		= color_rgba(oV.B.x,oV.B.y,oV.B.z,0);
                    g_VB.Add	(&uB,4);
                }

                // TC
                s16	tu,tv,frac,dummy;
                tu			= QC(oV.UV.begin()->x);
                tv			= QC(oV.UV.begin()->y);
                g_VB.Add	(&tu,2);
                g_VB.Add	(&tv,2);

                // frac
                float	f1	= (oV.P.y - frac_low.y)		/frac_Ysize;
                float	f2	= oV.P.distance_to(frac_low)/frac_Ysize;
                frac		= QC((f1+f2)/2.f);
                dummy		= 0;
                g_VB.Add	(&frac,	2);
                g_VB.Add	(&dummy,2);
            }

            g_VB.End		(&it->vb_id,&it->vb_start);
        }

        // Indices
        g_IB.Register	(LPWORD(&*it->ogf->faces.begin()),LPWORD(&*it->ogf->faces.end()),&it->ib_id,&it->ib_start);

        // SW
        if (it->ogf->progressive_test())
            g_SWI.Register	(&it->sw_id,&it->ogf->m_SWI);
    }
}
예제 #15
0
void CDeflector::OA_Export()
{
	if (UVpolys.empty()) return;

	// Correct normal
	//  (semi-proportional to pixel density)
	FPU::m64r		();
	Fvector			tN;
	tN.set			(0,0,0);
	float density	= 0;
	float fcount	= 0;
	for (UVIt it = UVpolys.begin(); it!=UVpolys.end(); it++)
	{
		Face	*F = it->owner;
		Fvector	SN;
		SN.set	(F->N);
		SN.mul	(1+EPS*F->CalcArea());
		tN.add	(SN);

		density	+= F->Shader().lm_density;
		fcount	+= 1.f;
	}
	if (tN.magnitude()>EPS_S && _valid(tN))	normal.set(tN).normalize();
	else									clMsg("* ERROR: Internal precision error in CDeflector::OA_Export");
	density			/= fcount;
	
	// Orbitrary Oriented Ortho - Projection
	Fmatrix		mView;
    Fvector		at,from,up,right,y;
	at.set		(0,0,0);
	from.add	(at,normal);
	y.set		(0,1,0);
	if (_abs(normal.y)>.99f)		y.set(1,0,0);
	right.crossproduct(y,normal);	right.normalize_safe();
	up.crossproduct(normal,right);	up.normalize_safe();
	mView.build_camera(from,at,up);

	Fbox bb; bb.invalidate();
	for (UVIt it = UVpolys.begin(); it!=UVpolys.end(); it++)
	{
		UVtri	*T = &*it;
		Face	*F = T->owner;
		Fvector	P;	// projected

		for (int i=0; i<3; i++) {
			mView.transform_tiny	(P,F->v[i]->P);
			T->uv[i].set			(P.x,P.y);
			bb.modify				(F->v[i]->P);
		}
	}
	bb.getsphere(Sphere.P,Sphere.R);

	// UV rect
	Fvector2		min,max,size;
	GetRect			(min,max);
	size.sub		(max,min);

	// Surface
	u32 dwWidth		= iCeil(size.x*g_params.m_lm_pixels_per_meter*density+.5f); clamp(dwWidth, 1u,512u-2*BORDER);
	u32 dwHeight	= iCeil(size.y*g_params.m_lm_pixels_per_meter*density+.5f); clamp(dwHeight,1u,512u-2*BORDER);
	layer.create	(dwWidth,dwHeight);
}
예제 #16
0
void CActor::cam_Update(float dt, float fFOV)
{
	if(m_holder)		return;

	if(mstate_real & mcClimb&&cam_active!=eacFreeLook)
		camUpdateLadder(dt);

	Fvector point={0,CameraHeight(),0}, dangle={0,0,0};
	

	Fmatrix				xform,xformR;
	xform.setXYZ		(0,r_torso.yaw,0);
	xform.translate_over(XFORM().c);

	// lookout
	if (this == Level().CurrentControlEntity())
	{
		if (!fis_zero(r_torso_tgt_roll)){
			Fvector src_pt,tgt_pt;
			float radius		= point.y*0.5f;
			float alpha			= r_torso_tgt_roll/2.f;
			float dZ			= ((PI_DIV_2-((PI+alpha)/2)));
			calc_point			(tgt_pt,radius,0,alpha);
			src_pt.set			(0,tgt_pt.y,0);
			// init valid angle
			float valid_angle	= alpha;
			// xform with roll
			xformR.setXYZ		(-r_torso.pitch,r_torso.yaw,-dZ);
			Fmatrix33			mat; 
			mat.i				= xformR.i;
			mat.j				= xformR.j;
			mat.k				= xformR.k;
			// get viewport params
			float w,h;
			float c				= viewport_near(w,h); w/=2.f;h/=2.f;
			// find tris
			Fbox box;
			box.invalidate		();
			box.modify			(src_pt);
			box.modify			(tgt_pt);
			box.grow			(c);

			// query
			Fvector				bc,bd		;
			Fbox				xf			; 
			xf.xform			(box,xform)	;
			xf.get_CD			(bc,bd)		;

			xrXRC				xrc			;
			xrc.box_options		(0)			;
			xrc.box_query		(Level().ObjectSpace.GetStaticModel(), bc, bd)		;
			u32 tri_count		= xrc.r_count();
			if (tri_count)		{
				float da		= 0.f;
				BOOL bIntersect	= FALSE;
				Fvector	ext		= {w,h,VIEWPORT_NEAR/2};
				if (test_point(xrc,xform,mat,ext,radius,alpha)){
					da			= PI/1000.f;
					if (!fis_zero(r_torso.roll))
						da		*= r_torso.roll/_abs(r_torso.roll);
					float angle = 0.f;
					for (; _abs(angle)<_abs(alpha); angle+=da)
						if (test_point(xrc,xform,mat,ext,radius,angle)) { bIntersect=TRUE; break; } 
					valid_angle	= bIntersect?angle:alpha;
				} 
			}
			r_torso.roll		= valid_angle*2.f;
			r_torso_tgt_roll	= r_torso.roll;
		}
		else
		{	
			r_torso_tgt_roll = 0.f;
			r_torso.roll = 0.f;
		}
	}
	if (!fis_zero(r_torso.roll))
	{
		float radius		= point.y*0.5f;
		float valid_angle	= r_torso.roll/2.f;
		calc_point			(point,radius,0,valid_angle);
		dangle.z			= (PI_DIV_2-((PI+valid_angle)/2));
	}

	float flCurrentPlayerY	= xform.c.y;

	// Smooth out stair step ups
	if ((character_physics_support()->movement()->Environment()==peOnGround) && (flCurrentPlayerY-fPrevCamPos>0)){
		fPrevCamPos			+= dt*1.5f;
		if (fPrevCamPos > flCurrentPlayerY)
			fPrevCamPos		= flCurrentPlayerY;
		if (flCurrentPlayerY-fPrevCamPos>0.2f)
			fPrevCamPos		= flCurrentPlayerY-0.2f;
		point.y				+= fPrevCamPos-flCurrentPlayerY;
	}else{
		fPrevCamPos			= flCurrentPlayerY;
	}
	float _viewport_near			= VIEWPORT_NEAR;
	// calc point
	xform.transform_tiny			(point);

	CCameraBase* C					= cam_Active();

	if(eacFirstEye == cam_active)
	{
//		CCameraBase* C				= cameras[eacFirstEye];
	
		xrXRC						xrc			;
		xrc.box_options				(0)			;
		xrc.box_query				(Level().ObjectSpace.GetStaticModel(), point, Fvector().set(VIEWPORT_NEAR,VIEWPORT_NEAR,VIEWPORT_NEAR) );
		u32 tri_count				= xrc.r_count();
		if (tri_count)
		{
			_viewport_near			= 0.01f;
		}
		else
		{
			xr_vector<ISpatial*> ISpatialResult;
			g_SpatialSpacePhysic->q_box(ISpatialResult, 0, STYPE_PHYSIC, point, Fvector().set(VIEWPORT_NEAR,VIEWPORT_NEAR,VIEWPORT_NEAR));
			for (u32 o_it=0; o_it<ISpatialResult.size(); o_it++)
			{
				CPHShell*		pCPHS= smart_cast<CPHShell*>(ISpatialResult[o_it]);
				if (pCPHS)
				{
					_viewport_near			= 0.01f;
					break;
				}
			}
		}
	}
/*
	{
		CCameraBase* C				= cameras[eacFirstEye];
		float oobox_size			= 2*VIEWPORT_NEAR;


		Fmatrix						_rot;
		_rot.k						= C->vDirection;
		_rot.c						= C->vPosition;
		_rot.i.crossproduct			(C->vNormal,	_rot.k);
		_rot.j.crossproduct			(_rot.k,		_rot.i);

		
		Fvector						vbox; 
		vbox.set					(oobox_size, oobox_size, oobox_size);


		Level().debug_renderer().draw_aabb  (C->vPosition, 0.05f, 0.051f, 0.05f, D3DCOLOR_XRGB(0,255,0));
		Level().debug_renderer().draw_obb  (_rot, Fvector().div(vbox,2.0f), D3DCOLOR_XRGB(255,0,0));

		dMatrix3					d_rot;
		PHDynamicData::FMXtoDMX		(_rot, d_rot);

		CPHActivationShape			activation_shape;
		activation_shape.Create		(point, vbox, this);

		dBodySetRotation			(activation_shape.ODEBody(), d_rot);

		CPHCollideValidator::SetDynamicNotCollide(activation_shape);
		activation_shape.Activate	(vbox,1,1.f,0.0F);

		point.set					(activation_shape.Position());
		
		activation_shape.Destroy	();
	}
*/
	C->Update						(point,dangle);
	C->f_fov						= fFOV;
	if(eacFirstEye != cam_active)
	{
		cameras[eacFirstEye]->Update	(point,dangle);
		cameras[eacFirstEye]->f_fov		= fFOV;
	}
	
	if( psActorFlags.test(AF_PSP) )
	{
		Cameras().Update			(C);
	}else
	{
		Cameras().Update			(cameras[eacFirstEye]);
	}

	fCurAVelocity			= vPrevCamDir.sub(cameras[eacFirstEye]->vDirection).magnitude()/Device.fTimeDelta;
	vPrevCamDir				= cameras[eacFirstEye]->vDirection;

	if (Level().CurrentEntity() == this)
	{
		Level().Cameras().Update	(C);
		if(eacFirstEye == cam_active && !Level().Cameras().GetCamEffector(cefDemo)){
			Cameras().ApplyDevice	(_viewport_near);
		}
	}
}
예제 #17
0
void	CBuild::BuildCForm	()
{
	Phase			("CFORM: construction...");
	//Status		("Building base mesh : vertices...");

	_mesh			mesh;						// a mesh object
	_decimater		decimater(mesh);			// a decimater object, connected to a mesh
	_HModQuadric	hModQuadric;				// use a quadric module
	decimater.add	(hModQuadric);				// register module at the decimater
	decimater.module(hModQuadric).set_max_err	(0.0001,false);	// error-limit 0.0001

	// Initializing mesh
	Status			("Building base mesh : vertices[%d]...",g_vertices.size());
	for (vecVertexIt _v=g_vertices.begin(); _v!=g_vertices.end(); _v++)	(*_v)->handle	= _mesh::InvalidVertexHandle.idx();

	Status			("Building base mesh : base faces[%d]...",g_faces.size());
	std::vector <_mesh::VertexHandle>	fhandles;
	xr_vector	<cform_FailFace>		failedfaces;
	cform_mergeprops					fmergeprops;

	for (vecFaceIt I=g_faces.begin(); I!=g_faces.end(); I++)
	{
		Progress	(float(I-g_faces.begin())/float(g_faces.size()));
		Face* F		= *I;
		if (F->Shader().flags.bCollision) 
		{
			// test correctness
			TestEdge	(F->v[0],F->v[1],F);
			TestEdge	(F->v[1],F->v[2],F);
			TestEdge	(F->v[2],F->v[0],F);

			// add vertices
			fhandles.clear	();
			for (u32 v=0; v<3; v++)
			{
				_mesh::VertexHandle	h	= _mesh::VertexHandle(F->v[v]->handle);
				if (_mesh::InvalidVertexHandle == h)	{ 
					Fvector& p			= F->v[v]->P; 
					h					= mesh.add_vertex	(_mesh::Point(p.x,p.y,p.z));
					F->v[v]->handle		= h.idx();
				}
				fhandles.push_back	(h);
			}

			// add face
			fmergeprops.material		= F->dwMaterialGame;
			fmergeprops.sector			= materials[F->dwMaterial].sector;
			_mesh::FaceHandle	hface	= mesh.add_face		(fhandles);
			if (hface == _mesh::InvalidFaceHandle)	{
				failedfaces.push_back		(cform_FailFace());
				failedfaces.back().P[0]		= F->v[0]->P;
				failedfaces.back().P[1]		= F->v[1]->P;
				failedfaces.back().P[2]		= F->v[2]->P;
				failedfaces.back().props	= fmergeprops.props;
			}
			else				mesh.face(hface).set_props	(fmergeprops.props);
		}
	}
	if (bCriticalErrCnt) {
		err_save	();
		clMsg		("MultipleEdges: %d faces",bCriticalErrCnt);
	}

	Status			("Building base mesh : models[%d]...",mu_refs.size());
	mesh.garbage_collection		();
	for (u32 ref=0; ref<mu_refs.size(); ref++)
		mu_refs[ref]->export_cform_game(mesh,failedfaces);

	Status			("Building base mesh : normals...");
	mesh.garbage_collection		();
	mesh.request_vertex_normals	();
	mesh.update_vertex_normals	();

	// Decimate
	Status			("Reconstructing mesh-topology...");
	clMsg			("%d faces failed topology check",	failedfaces.size());
	clMsg			("%f%% geometry/artist quality",	100.f * (1-float(failedfaces.size())/float(mesh.n_faces())));

	decimater.initialize	();      // let the decimater initialize the mesh and the modules

	int		nf_before		= int	(mesh.n_faces());
	int		nv_before		= int	(mesh.n_vertices());
	int		nc				= decimater.decimate	(nv_before);	// do decimation, as large, as possible
							mesh.garbage_collection	();
	int		nf_after		= int	(mesh.n_faces());
	int		nv_after		= int	(mesh.n_vertices());
	clMsg					("vertices: was[%d], now[%d] => %f %% left",nv_before,nv_after, 100.f*float(nv_after)/float(nv_before) );
	clMsg					("   faces: was[%d], now[%d] => %f %% left",nf_before,nf_after, 100.f*float(nf_after)/float(nf_before) );

	// Decimate
	Status			("Refactoring CFORM...");
	Fbox BB;	BB.invalidate();
	_mesh::VertexIter	vit	=mesh.vertices_begin(),vend=mesh.vertices_end();
	for (; vit!=vend; ++vit)
		BB.modify( reinterpret_cast<Fvector&>(mesh.point(vit)) );

	CDB::CollectorPacked	CL(BB,mesh.n_vertices(),mesh.n_faces());
	_mesh::FaceIter			fit=mesh.faces_begin(),fend=mesh.faces_end();
	for (; fit!=fend; ++fit){
		// get vertex-handles
		fhandles.clear	();
		for (_mesh::CFVIter fv_it=mesh.cfv_iter(fit); fv_it; ++fv_it)
			fhandles.push_back	(fv_it.handle());
		CL.add_face_D	(
			reinterpret_cast<Fvector&>(mesh.point	(fhandles[0])),
			reinterpret_cast<Fvector&>(mesh.point	(fhandles[1])),
			reinterpret_cast<Fvector&>(mesh.point	(fhandles[2])),
			fit->props	()
			);
	}
	Status			("Restoring fail-faces...");
	for (u32 it=0; it<failedfaces.size(); it++)		{
		cform_FailFace&	F	= failedfaces[it];
		CL.add_face_D		( F.P[0], F.P[1], F.P[2], F.props );
	}

	// Saving
	Status			("Saving...");
			nf_after		= int	(CL.getTS());
			nv_after		= int	(CL.getVS());
	clMsg					("vertices: was[%d], now[%d] => %f %% left",nv_before,nv_after, 100.f*float(nv_after)/float(nv_before) );
	clMsg					("   faces: was[%d], now[%d] => %f %% left",nf_before,nf_after, 100.f*float(nf_after)/float(nf_before) );
	string512		fn;
	IWriter*		MFS	= FS.w_open	(strconcat(fn,pBuild->path,"level.cform"));
	
	// Header
	hdrCFORM		hdr;
	hdr.version		= CFORM_CURRENT_VERSION;
	hdr.vertcount	= (u32)CL.getVS();
	hdr.facecount	= (u32)CL.getTS();
	hdr.aabb		= BB;
	MFS->w			(&hdr,sizeof(hdr));
	// Data
	MFS->w			(CL.getV(),(u32)CL.getVS()*sizeof(Fvector));
	MFS->w			(CL.getT(),(u32)CL.getTS()*sizeof(CDB::TRI));
	// Clear pDeflector (it is stored in the same memory space with dwMaterialGame)
	for (vecFaceIt I=g_faces.begin(); I!=g_faces.end(); I++)	{
		Face* F			= *I;
		F->pDeflector	= NULL;
	}
	FS.w_close		(MFS);
}