bool	CPHActivationShape::	Activate							(const Fvector need_size,u16 steps,float max_displacement,float max_rotation,bool	un_freeze_later/*	=false*/)										
{

#ifdef	DEBUG 
	if(ph_dbg_draw_mask.test(phDbgDrawDeathActivationBox))
	{
		DBG_OpenCashedDraw();
		Fmatrix M;
		PHDynamicData::DMXPStoFMX(dBodyGetRotation(m_body),dBodyGetPosition(m_body),M);
		Fvector v;dGeomBoxGetLengths(m_geom,cast_fp(v));v.mul(0.5f);
		DBG_DrawOBB(M,v,D3DCOLOR_XRGB(0,255,0));
	}
#endif
	VERIFY(m_geom&&m_body);
	CPHObject::activate();
	ph_world->Freeze();
	UnFreeze();
	max_depth=0.f;

	dGeomUserDataSetObjectContactCallback(m_geom,GetMaxDepthCallback)			;
	//ph_world->Step();
	ph_world->StepTouch();	
	u16		num_it =15;
	float	fnum_it=float(num_it);
	float	fnum_steps=float(steps);
	float	fnum_steps_r=1.f/fnum_steps;
	float	resolve_depth=0.01f;
	float	max_vel=max_depth/fnum_it*fnum_steps_r/fixed_step;
	float	limit_l_vel=_max(_max(need_size.x,need_size.y),need_size.z)/fnum_it*fnum_steps_r/fixed_step;

	if(limit_l_vel>default_l_limit)
		limit_l_vel=default_l_limit;

	if(max_vel>limit_l_vel)
		max_vel=limit_l_vel;

	float	max_a_vel=max_rotation/fnum_it*fnum_steps_r/fixed_step;

	if(max_a_vel>default_w_limit)
					max_a_vel=default_w_limit;

	//ph_world->CutVelocity(0.f,0.f);
	dGeomUserDataSetCallbackData(m_geom,this);
	dGeomUserDataSetObjectContactCallback( m_geom, ActivateTestDepthCallback );
	if( m_flags.test( flStaticEnvironment ) )
		dGeomUserDataAddObjectContactCallback(m_geom,StaticEnvironment);
	max_depth=0.f;
	
	Fvector from_size;
	Fvector step_size,size;
	dGeomBoxGetLengths(m_geom,cast_fp(from_size));
	step_size.sub(need_size,from_size);
	step_size.mul(fnum_steps_r);
	size.set(from_size);
	bool ret=false;
	V_PH_WORLD_STATE temp_state;
	ph_world->GetState(temp_state);
	for(int m=0;steps>m;++m)
	{
		//float param =fnum_steps_r*(1+m);
		//InterpolateBox(id,param);
		size.add(step_size);
		dGeomBoxSetLengths(m_geom,size.x,size.y,size.z);
		u16		attempts=10;
		do{
		
			ret=false;
			for(int i=0;num_it>i;++i)
			{
				max_depth=0.f;
				ph_world->Step();
				CHECK_POS(Position(),"pos after ph_world->Step()",false);
				ph_world->CutVelocity(max_vel,max_a_vel);
				CHECK_POS(Position(),"pos after CutVelocity",true);
				//if(m==0&&i==0)ph_world->GetState(temp_state);
				if(max_depth	<	resolve_depth) 
				{
						ret=true;
						break;
				}
			}
			attempts--;
		}while(!ret&&attempts>0);
#ifdef	DEBUG
		Msg("correction attempts %d",10-attempts);
#endif
	
	}
	RestoreVelocityState(temp_state);
	CHECK_POS(Position(),"pos after RestoreVelocityState(temp_state);",true);
	if(!un_freeze_later)ph_world->UnFreeze();
#ifdef	DEBUG 
	if(ph_dbg_draw_mask.test(phDbgDrawDeathActivationBox))
	{
		DBG_OpenCashedDraw();
		Fmatrix M;
		PHDynamicData::DMXPStoFMX(dBodyGetRotation(m_body),dBodyGetPosition(m_body),M);
		Fvector v;v.set(need_size);v.mul(0.5f);
		DBG_DrawOBB(M,v,D3DCOLOR_XRGB(0,255,255));
		DBG_ClosedCashedDraw(30000);
	}
#endif
	return ret;
}
Beispiel #2
0
float CExplosive::ExplosionEffect(collide::rq_results& storage, CExplosive*exp_obj,CPhysicsShellHolder*blasted_obj,  const Fvector &expl_centre, const float expl_radius) 
{
	
	const Fmatrix	&obj_xform=blasted_obj->XFORM();
	Fmatrix	inv_obj_form;inv_obj_form.invert(obj_xform);
	Fvector	local_exp_center;inv_obj_form.transform_tiny(local_exp_center,expl_centre);

	const Fbox &l_b1 = blasted_obj->BoundingBox();
	if(l_b1.contains(local_exp_center)) 
										return 1.f;
	Fvector l_c, l_d;l_b1.get_CD(l_c,l_d);
	float effective_volume=l_d.x*l_d.y*l_d.z;
	float max_s=effective_volume/(_min(_min(l_d.x,l_d.y),l_d.z));
	if(blasted_obj->PPhysicsShell()&&blasted_obj->PPhysicsShell()->isActive())
	{
		float ph_volume=blasted_obj->PPhysicsShell()->getVolume();
		if(ph_volume<effective_volume)effective_volume=ph_volume;
	}
	float effect=0.f;
#ifdef DEBUG
	if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
	{
		Fmatrix dbg_box_m;dbg_box_m.set(obj_xform);
		dbg_box_m.c.set(l_c);obj_xform.transform(dbg_box_m.c);
		DBG_DrawOBB(dbg_box_m,l_d,D3DCOLOR_XRGB(255,255,0));
	}
#endif

	for(u16 i=0;i<TEST_RAYS_PER_OBJECT;++i){
		Fvector l_source_p,l_end_p;
		l_end_p.random_point(l_d);
		l_end_p.add(l_c);
		obj_xform.transform_tiny(l_end_p);
		GetRaySourcePos(exp_obj,expl_centre,l_source_p);
		Fvector l_local_source_p;inv_obj_form.transform_tiny(l_local_source_p,l_source_p);
		if(l_b1.contains(l_local_source_p))
		{
			effect+=1.f;continue;
		}
		Fvector l_dir; l_dir.sub(l_end_p,l_source_p);
		float mag=l_dir.magnitude();
		
		if(fis_zero(mag)) return 1.f;

		l_dir.mul(1.f/mag);
#ifdef DEBUG
			if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
			{
			DBG_DrawPoint(l_source_p,0.1f,D3DCOLOR_XRGB(0,0,255));
			DBG_DrawPoint(l_end_p,0.1f,D3DCOLOR_XRGB(0,0,255));
			DBG_DrawLine(l_source_p,l_end_p,D3DCOLOR_XRGB(0,0,255));
			}
#endif
		
#ifdef DEBUG
		float l_S=effective_volume*(_abs(l_dir.dotproduct(obj_xform.i))/l_d.x+_abs(l_dir.dotproduct(obj_xform.j))/l_d.y+_abs(l_dir.dotproduct(obj_xform.k))/l_d.z);
		float add_eff=_sqrt(l_S/max_s)*TestPassEffect(l_source_p,l_dir,mag,expl_radius,storage,blasted_obj);
		effect+=add_eff;
		if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
		{
			Msg("dist %f,effect R %f",mag,expl_radius);
			Msg("test pass effect %f",add_eff);
			Msg("S effect %f",_sqrt(l_S/max_s));
			Msg("dist/overlap effect, %f",add_eff/_sqrt(l_S/max_s));
		}
#else
		float l_S=effective_volume*(_abs(l_dir.dotproduct(obj_xform.i))/l_d.x+_abs(l_dir.dotproduct(obj_xform.j))/l_d.y+_abs(l_dir.dotproduct(obj_xform.k))/l_d.z);
		effect+=_sqrt(l_S/max_s)*TestPassEffect(l_source_p,l_dir,mag,expl_radius,storage,blasted_obj);
#endif

	}
#ifdef DEBUG
	if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
	{
			Msg("damage effect %f",effect/TEST_RAYS_PER_OBJECT);
	}
#endif
	return effect/TEST_RAYS_PER_OBJECT;
	
}