Esempio n. 1
0
BOOL CObjectSpace::_RayQuery2	(collide::rq_results& r_dest, const collide::ray_defs& R, collide::rq_callback* CB, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object)
{
	// initialize query
	r_dest.r_clear		();
	r_temp.r_clear		();

	rq_target	s_mask	=	rqtStatic;
	rq_target	d_mask	=	rq_target(	((R.tgt&rqtObject)	?rqtObject:rqtNone		)|
										((R.tgt&rqtObstacle)?rqtObstacle:rqtNone	)|
										((R.tgt&rqtShape)	?rqtShape:rqtNone)		);
	u32			d_flags =	STYPE_COLLIDEABLE|((R.tgt&rqtObstacle)?STYPE_OBSTACLE:0)|((R.tgt&rqtShape)?STYPE_SHAPE:0);

	// Test static
	if (R.tgt&s_mask){ 
		xrc.ray_options	(R.flags);
		xrc.ray_query	(&Static,R.start,R.dir,R.range);
		if (xrc.r_count()){	
			CDB::RESULT* _I	= xrc.r_begin();
			CDB::RESULT* _E = xrc.r_end	();
			for (; _I!=_E; _I++)
				r_temp.append_result(rq_result().set(0,_I->range,_I->id));
		}
	}
	// Test dynamic
	if (R.tgt&d_mask){ 
		// Traverse object database
		g_SpatialSpace->q_ray	(r_spatial,0,d_flags,R.start,R.dir,R.range);
		for (u32 o_it=0; o_it<r_spatial.size(); o_it++){
			CObject*	collidable		= r_spatial[o_it]->dcast_CObject();
			if			(0==collidable)				continue;
			if			(collidable==ignore_object)	continue;
			ICollisionForm*	cform		= collidable->collidable.model;
			ECollisionFormType tp		= collidable->collidable.model->Type();
			if (((R.tgt&(rqtObject|rqtObstacle))&&(tp==cftObject))||((R.tgt&rqtShape)&&(tp==cftShape))){
				if (tb&&!tb(R,collidable,user_data))continue;
				cform->_RayQuery(R,r_temp);
			}
		}
	}
	if (r_temp.r_count()){
		r_temp.r_sort		();
		collide::rq_result* _I = r_temp.r_begin	();
		collide::rq_result* _E = r_temp.r_end	();
		for (; _I!=_E; _I++){
			r_dest.append_result(*_I);
			if (!(CB?CB(*_I,user_data):TRUE))						return r_dest.r_count();
			if (R.flags&(CDB::OPT_ONLYNEAREST|CDB::OPT_ONLYFIRST))	return r_dest.r_count();
		}
	}
	return r_dest.r_count();
}
Esempio n. 2
0
bool CBulletManager::CalcBullet (collide::rq_results & rq_storage, xr_vector<ISpatial*>& rq_spatial, SBullet* bullet, u32 delta_time)
{
	VERIFY					(bullet);

	float delta_time_sec	= float(delta_time)/1000.f;
	float range				= bullet->speed*delta_time_sec;
	
	float max_range					= bullet->max_dist - bullet->fly_dist;
	if(range>max_range) 
		range = max_range;

	//запомнить текущую скорость пули, т.к. в
	//RayQuery() она может поменяться из-за рикошетов
	//и столкновений с объектами
	Fvector cur_dir					= bullet->dir;
	bullet_test_callback_data		bullet_data;
	bullet_data.pBullet				= bullet;
	bullet_data.bStopTracing		= true;

	bullet->flags.ricochet_was		= 0;

	collide::ray_defs RD			(bullet->pos, bullet->dir, range, CDB::OPT_CULL, collide::rqtBoth);
	BOOL result						= FALSE;
	VERIFY							(!fis_zero(RD.dir.square_magnitude()));
	result							= Level().ObjectSpace.RayQuery(rq_storage, RD, firetrace_callback, &bullet_data, test_callback, NULL);
	
	if (result && bullet_data.bStopTracing) 
	{
		range						= (rq_storage.r_begin()+rq_storage.r_count()-1)->range;
	}
	range							= _max				(EPS_L,range);

	bullet->flags.skipped_frame = (Device.dwFrame >= bullet->frame_num);

	if(!bullet->flags.ricochet_was)	{
		//изменить положение пули
		bullet->pos.mad(bullet->pos, cur_dir, range);
		bullet->fly_dist += range;

		if(bullet->fly_dist>=bullet->max_dist)
			return false;

		Fbox level_box = Level().ObjectSpace.GetBoundingVolume();
		
/*		if(!level_box.contains(bullet->pos))
			return false;
*/
		if(!((bullet->pos.x>=level_box.x1) && 
			 (bullet->pos.x<=level_box.x2) && 
			 (bullet->pos.y>=level_box.y1) && 
//			 (bullet->pos.y<=level_box.y2) && 
			 (bullet->pos.z>=level_box.z1) && 
			 (bullet->pos.z<=level_box.z2))	)
			 return false;

		//изменить скорость и направление ее полета
		//с учетом гравитации
		bullet->dir.mul(bullet->speed);

		Fvector air_resistance = bullet->dir;
		if (GameID() == GAME_SINGLE)
			air_resistance.mul(-m_fAirResistanceK*delta_time_sec);
		else
			air_resistance.mul(-bullet->air_resistance*(bullet->speed)/(bullet->max_speed)*delta_time_sec);
///		Msg("Speed - %f; ar - %f, %f", bullet->dir.magnitude(), air_resistance.magnitude(), air_resistance.magnitude()/bullet->dir.magnitude()*100);

		bullet->dir.add(air_resistance);
		bullet->dir.y -= m_fGravityConst*delta_time_sec;

		bullet->speed = bullet->dir.magnitude();
		VERIFY(_valid(bullet->speed));
		VERIFY(!fis_zero(bullet->speed));
		
		// by Real Wolf 11.07.2014.
		R_ASSERT(bullet->speed);

		//вместо normalize(),	 чтоб не считать 2 раза magnitude()
		bullet->dir.x /= bullet->speed;
		bullet->dir.y /= bullet->speed;
		bullet->dir.z /= bullet->speed;
	}

	if(bullet->speed<m_fMinBulletSpeed)
		return false;

	return true;
}
Esempio n. 3
0
BOOL CObjectSpace::RayQuery	(collide::rq_results& r_dest, ICollisionForm* target, const collide::ray_defs& R)
{
	VERIFY					(target);
	r_dest.r_clear			();
	return target->_RayQuery(R,r_dest);
}
Esempio n. 4
0
BOOL CObjectSpace::_RayQuery	(collide::rq_results& r_dest, const collide::ray_defs& R, collide::rq_callback* CB, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object)
{
#ifdef DEBUG
	if (R.range<EPS || !_valid(R.range))
		Debug.fatal			(DEBUG_INFO,"Invalid RayQuery range passed: %f.",R.range);
#endif
	// initialize query
	r_dest.r_clear			();
	r_temp.r_clear			();

	Flags32		sd_test;	sd_test.assign	(R.tgt);
	rq_target	next_test	= R.tgt;

	rq_result	s_res;
	ray_defs	s_rd		(R.start,R.dir,R.range,CDB::OPT_ONLYNEAREST|R.flags,R.tgt);
	ray_defs	d_rd		(R.start,R.dir,R.range,CDB::OPT_ONLYNEAREST|R.flags,R.tgt);
	rq_target	s_mask	=	rqtStatic;
	rq_target	d_mask	=	rq_target(	((R.tgt&rqtObject)	?rqtObject:rqtNone		)|
										((R.tgt&rqtObstacle)?rqtObstacle:rqtNone	)|
										((R.tgt&rqtShape)	?rqtShape:rqtNone)		);
	u32			d_flags =	STYPE_COLLIDEABLE|((R.tgt&rqtObstacle)?STYPE_OBSTACLE:0)|((R.tgt&rqtShape)?STYPE_SHAPE:0);

	s_res.set				(0,s_rd.range,-1);
	do{
		if ((R.tgt&s_mask)&&sd_test.is(s_mask)&&(next_test&s_mask)){ 
			s_res.set		(0,s_rd.range,-1);
			// Test static model
			if (s_rd.range>EPS){
				xrc.ray_options	(s_rd.flags);
				xrc.ray_query	(&Static,s_rd.start,s_rd.dir,s_rd.range);
				if (xrc.r_count()){	
					if (s_res.set_if_less(xrc.r_begin())){
						// set new static start & range
						s_rd.range	-=	(s_res.range+EPS_L);
						s_rd.start.mad	(s_rd.dir,s_res.range+EPS_L);
						s_res.range	= R.range-s_rd.range-EPS_L;
#ifdef DEBUG
						if (!(fis_zero(s_res.range,EPS) || s_res.range>=0.f))
							Debug.fatal(DEBUG_INFO,"Invalid RayQuery static range: %f (%f). /#1/",s_res.range,s_rd.range);
#endif
					}
				}
			}
			if (!s_res.valid())	sd_test.set(s_mask,FALSE);
		}
		if ((R.tgt&d_mask)&&sd_test.is_any(d_mask)&&(next_test&d_mask)){ 
			r_temp.r_clear	();

			if (d_rd.range>EPS){
				// Traverse object database
				g_SpatialSpace->q_ray		(r_spatial,0,d_flags,d_rd.start,d_rd.dir,d_rd.range);
				// Determine visibility for dynamic part of scene
				for (u32 o_it=0; o_it<r_spatial.size(); o_it++){
					CObject*	collidable		= r_spatial[o_it]->dcast_CObject();
					if			(0==collidable)				continue;
					if			(collidable==ignore_object)	continue;
					ICollisionForm*	cform		= collidable->collidable.model;
					ECollisionFormType tp		= collidable->collidable.model->Type();
					if (((R.tgt&(rqtObject|rqtObstacle))&&(tp==cftObject))||((R.tgt&rqtShape)&&(tp==cftShape))){
						if (tb&&!tb(d_rd,collidable,user_data))continue;
						cform->_RayQuery(d_rd,r_temp);
					}
#ifdef DEBUG
					if (!((0==r_temp.r_count()) || (r_temp.r_count()&&(fis_zero(r_temp.r_begin()->range, EPS)||(r_temp.r_begin()->range>=0.f)))))
						Debug.fatal(DEBUG_INFO,"Invalid RayQuery dynamic range: %f (%f). /#2/",r_temp.r_begin()->range,d_rd.range);
#endif
				}
			}
			if (r_temp.r_count()){
				// set new dynamic start & range
				rq_result& d_res = *r_temp.r_begin();
				d_rd.range	-= (d_res.range+EPS_L);
				d_rd.start.mad(d_rd.dir,d_res.range+EPS_L);
				d_res.range	= R.range-d_rd.range-EPS_L;
#ifdef DEBUG
				if (!(fis_zero(d_res.range,EPS) || d_res.range>=0.f))
					Debug.fatal(DEBUG_INFO,"Invalid RayQuery dynamic range: %f (%f). /#3/",d_res.range,d_rd.range);
#endif
			}else{
				sd_test.set(d_mask,FALSE);
			}
		}
		if (s_res.valid()&&r_temp.r_count()){
			// all test return result
			if	(s_res.range<r_temp.r_begin()->range){
				// static nearer
				BOOL need_calc			= CB?CB(s_res,user_data):TRUE;
				next_test				= need_calc?s_mask:rqtNone; 
				r_dest.append_result	(s_res);
			}else{
				// dynamic nearer
				BOOL need_calc			= CB?CB(*r_temp.r_begin(),user_data):TRUE;
				next_test				= need_calc?d_mask:rqtNone;	
				r_dest.append_result	(*r_temp.r_begin());
			}
		}else if (s_res.valid())	{
			// only static return result
			BOOL need_calc				= CB?CB(s_res,user_data):TRUE;
			next_test					= need_calc?s_mask:rqtNone;
			r_dest.append_result		(s_res);
		}else if (r_temp.r_count())	{
			// only dynamic return result
			BOOL need_calc				= CB?CB(*r_temp.r_begin(),user_data):TRUE;
			next_test					= need_calc?d_mask:rqtNone;
			r_dest.append_result		(*r_temp.r_begin());
		}else{
			// nothing selected
			next_test			= rqtNone;
		}
		if ((R.flags&CDB::OPT_ONLYFIRST)||(R.flags&CDB::OPT_ONLYNEAREST)) break;
	} while (next_test!=rqtNone)		;
	return r_dest.r_count	()	;
}
Esempio n. 5
0
BOOL CObjectSpace::_RayQuery3	(collide::rq_results& r_dest, const collide::ray_defs& R, collide::rq_callback* CB, LPVOID user_data, collide::test_callback* tb, CObject* ignore_object)
{
	// initialize query
	r_dest.r_clear			();

	ray_defs	d_rd		(R);
	ray_defs	s_rd		(R.start,R.dir,R.range,CDB::OPT_ONLYNEAREST|R.flags,R.tgt);
	rq_target	s_mask		=	rqtStatic;
	rq_target	d_mask		=	rq_target(	((R.tgt&rqtObject)	?rqtObject:rqtNone		)|
											((R.tgt&rqtObstacle)?rqtObstacle:rqtNone	)|
											((R.tgt&rqtShape)	?rqtShape:rqtNone)		);
	u32			d_flags		=	STYPE_COLLIDEABLE|((R.tgt&rqtObstacle)?STYPE_OBSTACLE:0)|((R.tgt&rqtShape)?STYPE_SHAPE:0);
	float		d_range		= 0.f;

	do{
		r_temp.r_clear		();
		if (R.tgt&s_mask){
			// static test allowed

			// test static
			xrc.ray_options		(s_rd.flags);
			xrc.ray_query		(&Static,s_rd.start,s_rd.dir,s_rd.range);

			if (xrc.r_count())	{	
				VERIFY			(xrc.r_count()==1);
				rq_result		s_res;
				s_res.set		(0,xrc.r_begin()->range,xrc.r_begin()->id);
				// update dynamic test range
				d_rd.range		= s_res.range;
				// set next static start & range
				s_rd.range		-= (s_res.range+EPS_L);
				s_rd.start.mad	(s_rd.dir,s_res.range+EPS_L);
				s_res.range		= R.range-s_rd.range-EPS_L;
				r_temp.append_result(s_res);
			}else{
				d_rd.range		= s_rd.range;
			}
		}
		// test dynamic
		if (R.tgt&d_mask)		{ 
			// Traverse object database
			g_SpatialSpace->q_ray	(r_spatial,0,d_flags,d_rd.start,d_rd.dir,d_rd.range);
			for (u32 o_it=0; o_it<r_spatial.size(); o_it++){
				CObject*	collidable		= r_spatial[o_it]->dcast_CObject();
				if			(0==collidable)				continue;
				if			(collidable==ignore_object)	continue;
				ICollisionForm*	cform		= collidable->collidable.model;
				ECollisionFormType tp		= collidable->collidable.model->Type();
				if (((R.tgt&(rqtObject|rqtObstacle))&&(tp==cftObject))||((R.tgt&rqtShape)&&(tp==cftShape))){
					if (tb&&!tb(d_rd,collidable,user_data))continue;
					u32 r_cnt				= r_temp.r_count();
					cform->_RayQuery		(d_rd,r_temp);
					for (int k=r_cnt; k<r_temp.r_count(); k++){
						rq_result& d_res	= *(r_temp.r_begin()+k);
						d_res.range			+= d_range;
					}
				}
			}
		}
		// set dynamic ray def
		d_rd.start			= s_rd.start;
		d_range				= R.range-s_rd.range;
		if (r_temp.r_count()){
			r_temp.r_sort		();
			collide::rq_result* _I = r_temp.r_begin	();
			collide::rq_result* _E = r_temp.r_end	();
			for (; _I!=_E; _I++){
				r_dest.append_result(*_I);
				if (!(CB?CB(*_I,user_data):TRUE))	return r_dest.r_count();
				if (R.flags&CDB::OPT_ONLYFIRST)		return r_dest.r_count();
			}
		}
		if ((R.flags&(CDB::OPT_ONLYNEAREST|CDB::OPT_ONLYFIRST)) && r_dest.r_count()) return r_dest.r_count();
	}while(r_temp.r_count());
	return r_dest.r_count()	;
}