示例#1
0
void fixFrictionVector( dBodyID b1, dBodyID b2, dContact& contact )
{
	dBodyGetPointVel(b1, contact.geom.pos[0], contact.geom.pos[1], contact.geom.pos[2], contact.fdir1);
	dVector3 fdir1_b2;
	if (b2)
	{
		dBodyGetPointVel(b2, contact.geom.pos[0], contact.geom.pos[1],	contact.geom.pos[2], fdir1_b2);
		contact.fdir1[0] -= fdir1_b2[0];
		contact.fdir1[1] -= fdir1_b2[1];
		contact.fdir1[2] -= fdir1_b2[2];
	}
	// at this point, contact[i].fdir1 is the relative tangent velocity of the two bodies.
	dCROSS(contact.fdir1, =, contact.fdir1, contact.geom.normal);
	// now, contact[i].fdir1 is perpendicular to both the normal and
	// the relative tangent velocity.
	double length = sqrt(contact.fdir1[0] * contact.fdir1[0]
	       			   + contact.fdir1[1] * contact.fdir1[1]
				       + contact.fdir1[2] * contact.fdir1[2]);
	if (length > 1e-12)
	{
	       // we only use our calculated direction if it has enough precision
	       contact.fdir1[0] /= length;
	       contact.fdir1[1] /= length;
	       contact.fdir1[2] /= length;
	       dNormalize3(contact.fdir1);
	       contact.surface.mode |= dContactFDir1;
	}

}
示例#2
0
void	CCharacterPhysicsSupport::	RemoveActiveWeaponCollision		()
{
	

	VERIFY( m_pPhysicsShell );
	VERIFY( m_weapon_attach_bone );
	VERIFY( !m_weapon_geoms.empty() );
	xr_vector<CODEGeom*>::iterator ii =m_weapon_geoms.begin(), ee = m_weapon_geoms.end();
	Fmatrix m0;
	(*ii)->get_xform( m0 );
	CPhysicsElement* root = m_active_item_obj->PPhysicsShell()->get_ElementByStoreOrder( 0 );
	CODEGeom *rg = root->geometry( 0 );
	VERIFY( rg );
	Fmatrix m1;
	rg->get_xform( m1 );

	Fmatrix me;
	root->GetGlobalTransformDynamic( &me );

	Fmatrix m1_to_e = Fmatrix().mul_43( Fmatrix().invert( m1 ), me );

	Fmatrix m0e = Fmatrix().mul_43( m0, m1_to_e );
	root->SetTransform( m0e );

	for( ;ii!=ee; ++ii )
	{
		CODEGeom *g  =(*ii);

		//g->dbg_draw( 0.01f, D3DCOLOR_XRGB( 0, 0, 255 ), Flags32() );

		m_weapon_attach_bone->remove_geom( g );
		g->destroy();
		xr_delete(g);
	}


	//m_active_item_obj->PPhysicsShell()->dbg_draw_geometry( 0.2f, D3DCOLOR_XRGB( 255, 0, 100 ) );
	
	Fvector a_vel, l_vel;
	const Fvector& mc = root->mass_Center();
	dBodyGetPointVel( m_weapon_attach_bone->get_body(),mc.x, mc.y, mc.z, cast_fp(l_vel) );
	m_weapon_attach_bone->get_AngularVel( a_vel );
	
	root->set_AngularVel( a_vel );
	root->set_LinearVel( l_vel );
	
	m_weapon_geoms.clear();
	m_weapon_attach_bone = 0;
	m_active_item_obj	= 0;

	bone_fix_clear();
}
示例#3
0
void  TContactShotMark(CDB::TRI* T,dContactGeom* c)
{
	dBodyID b=dGeomGetBody(c->g1);
	dxGeomUserData* data;
	bool b_invert_normal=false;
	if(!b) 
	{
		b=dGeomGetBody(c->g2);
		data=dGeomGetUserData(c->g2);
		b_invert_normal=true;
	}
	else
	{
		data=dGeomGetUserData(c->g1);
	}
	if(!b) return;
	dVector3 vel;
	dMass m;
	dBodyGetMass(b,&m);
	dBodyGetPointVel(b,c->pos[0],c->pos[1],c->pos[2],vel);
	dReal vel_cret=dFabs(dDOT(vel,c->normal))* _sqrt(m.mass);
	Fvector to_camera;to_camera.sub(cast_fv(c->pos),Device.vCameraPosition);
	float square_cam_dist=to_camera.square_magnitude();
	if(data)
	{
		SGameMtlPair* mtl_pair		= GMLib.GetMaterialPair(T->material,data->material);
		if(mtl_pair)
		{
			//if(vel_cret>Pars.vel_cret_wallmark && !mtl_pair->CollideMarks.empty())
			if(vel_cret>Pars::vel_cret_wallmark && !mtl_pair->m_pCollideMarks->empty())
			{
				//ref_shader pWallmarkShader = mtl_pair->CollideMarks[::Random.randI(0,mtl_pair->CollideMarks.size())];
				wm_shader WallmarkShader = mtl_pair->m_pCollideMarks->GenerateWallmark();
				//ref_shader pWallmarkShader = mtl_pair->CollideMarks[::Random.randI(0,mtl_pair->CollideMarks.size())];
				Level().ph_commander().add_call(new CPHOnesCondition(),new CPHWallMarksCall( *((Fvector*)c->pos),T,WallmarkShader));
			}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			if(square_cam_dist<SQUARE_SOUND_EFFECT_DIST)
			{
			
				SGameMtl* static_mtl =  GMLib.GetMaterialByIdx(T->material);
				if(!static_mtl->Flags.test(SGameMtl::flPassable))
				{
					if(vel_cret>Pars::vel_cret_sound)
					{
						if(!mtl_pair->CollideSounds.empty())
						{
							float volume=collide_volume_min+vel_cret*(collide_volume_max-collide_volume_min)/(_sqrt(mass_limit)*default_l_limit-Pars::vel_cret_sound);
							GET_RANDOM(mtl_pair->CollideSounds).play_no_feedback(0,0,0,((Fvector*)c->pos),&volume);
						}
					}
				}
				else
				{
					if(data->ph_ref_object&&!mtl_pair->CollideSounds.empty())
					{
						CPHSoundPlayer* sp=NULL;
						sp=data->ph_ref_object->ph_sound_player();
						if(sp) sp->Play(mtl_pair,*(Fvector*)c->pos);
					}
				}
			}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			if(square_cam_dist<SQUARE_PARTICLE_EFFECT_DIST)
			{
				if(vel_cret>Pars::vel_cret_particles && !mtl_pair->CollideParticles.empty())
				{
					LPCSTR ps_name = *mtl_pair->CollideParticles[::Random.randI(0,mtl_pair->CollideParticles.size())];
					//отыграть партиклы столкновения материалов
					Level().ph_commander().add_call(new CPHOnesCondition(),new CPHParticlesPlayCall(*c,b_invert_normal,ps_name));
				}
			}
		}
	}
 }
示例#4
0
文件: dball.cpp 项目: EdgarSun/opende
void
dxJointDBall::getInfo2( dxJoint::Info2 *info )
{
    info->erp = erp;
    info->cfm[0] = cfm;

    dVector3 globalA1, globalA2;
    dBodyGetRelPointPos(node[0].body, anchor1[0], anchor1[1], anchor1[2], globalA1);
    if (node[1].body)
        dBodyGetRelPointPos(node[1].body, anchor2[0], anchor2[1], anchor2[2], globalA2);
    else
        dCopyVector3(globalA2, anchor2);

    dVector3 q;
    dSubtractVectors3(q, globalA1, globalA2);

#ifdef dSINGLE
    const dReal MIN_LENGTH = REAL(1e-7);
#else
    const dReal MIN_LENGTH = REAL(1e-12);
#endif

    if (dCalcVectorLength3(q) < MIN_LENGTH) {
        // too small, let's choose an arbitrary direction
        // heuristic: difference in velocities at anchors
        dVector3 v1, v2;
        dBodyGetPointVel(node[0].body, globalA1[0], globalA1[1], globalA1[2], v1);
        if (node[1].body)
            dBodyGetPointVel(node[1].body, globalA2[0], globalA2[1], globalA2[2], v2);
        else
            dSetZero(v2, 3);
        dSubtractVectors3(q, v1, v2);

        if (dCalcVectorLength3(q) < MIN_LENGTH) {
            // this direction is as good as any
            q[0] = 1;
            q[1] = 0;
            q[2] = 0;
        }
    }
    dNormalize3(q);

    info->J1l[0] = q[0];
    info->J1l[1] = q[1];
    info->J1l[2] = q[2];

    dVector3 relA1;
    dBodyVectorToWorld(node[0].body,
                       anchor1[0], anchor1[1], anchor1[2],
                       relA1);

    dMatrix3 a1m;
    dSetZero(a1m, 12);
    dSetCrossMatrixMinus(a1m, relA1, 4);

    dMultiply1_331(info->J1a, a1m, q);

    if (node[1].body) {
        info->J2l[0] = -q[0];
        info->J2l[1] = -q[1];
        info->J2l[2] = -q[2];

        dVector3 relA2;
        dBodyVectorToWorld(node[1].body,
                           anchor2[0], anchor2[1], anchor2[2],
                           relA2);
        dMatrix3 a2m;
        dSetZero(a2m, 12);
        dSetCrossMatrixPlus(a2m, relA2, 4);
        dMultiply1_331(info->J2a, a2m, q);
    }
    
    const dReal k = info->fps * info->erp;
    info->c[0] = k * (targetDistance - dCalcPointsDistance3(globalA1, globalA2));

}
示例#5
0
void CPHDestroyable::NotificatePart(CPHDestroyableNotificate *dn)
{
	CPhysicsShell	*own_shell=PPhysicsShellHolder()->PPhysicsShell()			;
	CPhysicsShell	*new_shell=dn->PPhysicsShellHolder()->PPhysicsShell()		;
	IKinematics		*own_K =smart_cast<IKinematics*>(PPhysicsShellHolder()->Visual());
	IKinematics		*new_K =smart_cast<IKinematics*>(dn->PPhysicsShellHolder()->Visual())	;
	VERIFY			(own_K&&new_K&&own_shell&&new_shell)						;
	CInifile		*own_ini  =own_K->LL_UserData()								;
	CInifile		*new_ini  =new_K->LL_UserData()								;
	//////////////////////////////////////////////////////////////////////////////////	
	Fmatrix			own_transform;
	own_shell		->GetGlobalTransformDynamic		(&own_transform)			;
	new_shell		->SetGlTransformDynamic			(own_transform)				;
	////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////////////
	float						random_min										=1.f	;  
	float						random_hit_imp									=1.f	;
	////////////////////////////////////////////////////////////////////////////////////
	u16							ref_bone										=own_K->LL_GetBoneRoot();

	float						imp_transition_factor							=1.f	;
	float						lv_transition_factor							=1.f	;
	float						av_transition_factor							=1.f	;
	////////////////////////////////////////////////////////////////////////////////////
	if(own_ini&&own_ini->section_exist("impulse_transition_to_parts"))
	{
		random_min				=own_ini->r_float("impulse_transition_to_parts","random_min");
		random_hit_imp			=own_ini->r_float("impulse_transition_to_parts","random_hit_imp");
		////////////////////////////////////////////////////////
		if(own_ini->line_exist("impulse_transition_to_parts","ref_bone"))
			ref_bone				=own_K->LL_BoneID(own_ini->r_string("impulse_transition_to_parts","ref_bone"));
		imp_transition_factor	=own_ini->r_float("impulse_transition_to_parts","imp_transition_factor");
		lv_transition_factor	=own_ini->r_float("impulse_transition_to_parts","lv_transition_factor");
		av_transition_factor	=own_ini->r_float("impulse_transition_to_parts","av_transition_factor");

		if(own_ini->section_exist("collide_parts"))
		{
			if(own_ini->line_exist("collide_parts","small_object"))
			{
				new_shell->SetSmall();
			}
			if(own_ini->line_exist("collide_parts","ignore_small_objects"))
			{
				new_shell->SetIgnoreSmall();
			}
		}
	}

	if(new_ini&&new_ini->section_exist("impulse_transition_from_source_bone"))
	{
		//random_min				=new_ini->r_float("impulse_transition_from_source_bone","random_min");
		//random_hit_imp			=new_ini->r_float("impulse_transition_from_source_bone","random_hit_imp");
		////////////////////////////////////////////////////////
		if(new_ini->line_exist("impulse_transition_from_source_bone","ref_bone"))
			ref_bone				=own_K->LL_BoneID(new_ini->r_string("impulse_transition_from_source_bone","ref_bone"));
		imp_transition_factor	=new_ini->r_float("impulse_transition_from_source_bone","imp_transition_factor");
		lv_transition_factor	=new_ini->r_float("impulse_transition_from_source_bone","lv_transition_factor");
		av_transition_factor	=new_ini->r_float("impulse_transition_from_source_bone","av_transition_factor");
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////////


		dBodyID own_body=own_shell->get_Element(ref_bone)->get_body()			;

		u16 new_el_number = new_shell->get_ElementsNumber()									;

		for(u16 i=0;i<new_el_number;++i)
		{
			CPhysicsElement* e=new_shell->get_ElementByStoreOrder(i);
			float random_hit=random_min*e->getMass();
			if(m_fatal_hit.is_valide() && m_fatal_hit.bone()!=BI_NONE )
			{
				Fvector pos;
				Fmatrix m;m.set(own_K->LL_GetTransform(m_fatal_hit.bone()));
				m.mulA_43		(PPhysicsShellHolder()->XFORM());
				m.transform_tiny(pos,m_fatal_hit.bone_space_position());
				e->applyImpulseVsGF(pos,m_fatal_hit.direction(),m_fatal_hit.phys_impulse()*imp_transition_factor);
				random_hit+=random_hit_imp*m_fatal_hit.phys_impulse();
			}
			Fvector rnd_dir;rnd_dir.random_dir();
			e->applyImpulse(rnd_dir,random_hit);
			Fvector mc; mc.set(e->mass_Center());
			dVector3 res_lvell;
			dBodyGetPointVel(own_body,mc.x,mc.y,mc.z,res_lvell);
			cast_fv(res_lvell).mul(lv_transition_factor);
			e->set_LinearVel(cast_fv(res_lvell));
			
			Fvector res_avell;res_avell.set(cast_fv(dBodyGetAngularVel(own_body)));
			res_avell.mul(av_transition_factor);
			e->set_AngularVel(res_avell);
		}
	




	new_shell->Enable();
	new_shell->EnableCollision();
	dn->PPhysicsShellHolder()->setVisible(TRUE);
	dn->PPhysicsShellHolder()->setEnabled(TRUE);

	if(own_shell->IsGroupObject())
		new_shell->RegisterToCLGroup(own_shell->GetCLGroup());//CollideBits
	CPHSkeleton* ps=dn->PPhysicsShellHolder()->PHSkeleton();
	if(ps)
	{
	
		if(own_ini&&own_ini->section_exist("autoremove_parts"))
		{
			ps->SetAutoRemove(1000*(READ_IF_EXISTS(own_ini,r_u32,"autoremove_parts","time",ps->DefaultExitenceTime())));
		}

		if(new_ini&&new_ini->section_exist("autoremove"))
		{
			ps->SetAutoRemove(1000*(READ_IF_EXISTS(new_ini,r_u32,"autoremove","time",ps->DefaultExitenceTime())));
		}
	}

}
void PhysicsSpace::collisionCallback (dGeomID o1, dGeomID o2)
{
    StatRealElem *NCollisionTestsStatElem = StatCollector::getGlobalElem(PhysicsHandler::statNCollisionTests);
    if(NCollisionTestsStatElem) { NCollisionTestsStatElem->add(1.0f); }

    if (dGeomIsSpace (o1) || dGeomIsSpace (o2))
    {
        // colliding a space with something
        dSpaceCollide2 (o1,o2,reinterpret_cast<void *>(this),&PhysicsSpace::collisionCallback);
        // collide all geoms internal to the space(s)
        if (dGeomIsSpace (o1)) dSpaceCollide (dGeomGetSpace(o1),reinterpret_cast<void *>(this),&PhysicsSpace::collisionCallback);
        if (dGeomIsSpace (o2)) dSpaceCollide (dGeomGetSpace(o2),reinterpret_cast<void *>(this),&PhysicsSpace::collisionCallback);
    }
    else
    {
        _DiscardCollision = false;

        // colliding two non-space geoms, so generate contact
        // points between o1 and o2
        Int32 numContacts = dCollide(o1, o2, _ContactJoints.size(), 
            &(_ContactJoints[0].geom), sizeof(dContact));
    
        StatRealElem *NCollisionsStatElem = StatCollector::getGlobalElem(PhysicsHandler::statNCollisions);
        if(NCollisionsStatElem) { NCollisionsStatElem->add(static_cast<Real32>(numContacts)); }

        if(numContacts>0)
        {
            Vec3f v1,v2,normal;
            Pnt3f position;
            dVector3 odeVec;
            Real32 projectedNormalSpeed;
            for (Int32 i=0; i < numContacts; i++)
            {
                normal += Vec3f(&_ContactJoints[i].geom.normal[0]);
                position += Vec3f(&_ContactJoints[i].geom.pos[0]);
                if(dGeomGetBody(o1))
                {
                    dBodyGetPointVel(dGeomGetBody(o1), _ContactJoints[i].geom.pos[0], _ContactJoints[i].geom.pos[1], _ContactJoints[i].geom.pos[2],odeVec);
                    v1 += Vec3f(&odeVec[0]);
                }
                if(dGeomGetBody(o2))
                {
                    dBodyGetPointVel(dGeomGetBody(o2), _ContactJoints[i].geom.pos[0], _ContactJoints[i].geom.pos[1], _ContactJoints[i].geom.pos[2],odeVec);
                    v2 += Vec3f(&odeVec[0]);
                }
            }

            normal = normal * (1.0f/static_cast<Real32>(numContacts));
            position = position * (1.0f/static_cast<Real32>(numContacts));
            v1 = v1 * (1.0f/static_cast<Real32>(numContacts));
            v2 = v2 * (1.0f/static_cast<Real32>(numContacts));
            projectedNormalSpeed = (v1+v2).projectTo(normal);

            //TODO: Add a way to get the PhysicsGeomUnrecPtr from the GeomIDs so that the PhysicsGeomUnrecPtr can be 
            //sent to the collision event
            produceCollision(position,
                                normal,
                                NULL,
                                NULL,
                                dGeomGetCategoryBits(o1),
                                dGeomGetCollideBits (o1),
                                dGeomGetCategoryBits(o2),
                                dGeomGetCollideBits (o2),
                                v1,
                                v2,
                                osgAbs(projectedNormalSpeed));

            UInt32 Index(0);
            for(; Index<_CollisionListenParamsVec.size() ; ++Index)
            {
                if((dGeomGetCategoryBits(o1) & _CollisionListenParamsVec[Index]._Category) || (dGeomGetCategoryBits(o2) & _CollisionListenParamsVec[Index]._Category))
                {
                    break;
                }
            }
            if(Index < _CollisionListenParamsVec.size())
            {
                for(UInt32 i(0); i<_CollisionListenParamsVec.size() ; ++i)
                {
                    if( ((dGeomGetCategoryBits(o1) & _CollisionListenParamsVec[i]._Category) || (dGeomGetCategoryBits(o2) & _CollisionListenParamsVec[i]._Category)) &&
                         (osgAbs(projectedNormalSpeed) >= _CollisionListenParamsVec[i]._SpeedThreshold)
                        )
                    {
                        //TODO: Add a way to get the PhysicsGeomUnrecPtr from the GeomIDs so that the PhysicsGeomUnrecPtr can be 
                        //sent to the collision event
                        produceCollision(_CollisionListenParamsVec[i]._Listener,
                                position,
                                normal,
                                NULL,
                                NULL,
                                dGeomGetCategoryBits(o1),
                                dGeomGetCollideBits (o1),
                                dGeomGetCategoryBits(o2),
                                dGeomGetCollideBits (o2),
                                v1,
                                v2,
                                osgAbs(projectedNormalSpeed));
                    }
                }
            }
        }
        if(!_DiscardCollision)
        {
            // add these contact points to the simulation
            for (Int32 i=0; i < numContacts; i++)
            {

                getCollisionContact(dGeomGetCategoryBits(o1), dGeomGetCategoryBits(o2))->updateODEContactJoint(_ContactJoints[i]);
                dJointID jointId = dJointCreateContact(_CollideWorldID, 
                    _ColJointGroupId, 
                    &_ContactJoints[i]);

                dJointAttach(jointId, dGeomGetBody(o1), dGeomGetBody(o2));
            }
        }
    }
}
void PhysicsBody::getPointVel(const Vec3f &v, Vec3f &result)
{
    dVector3 t;
    dBodyGetPointVel(_BodyID, v.x(), v.y(), v.z(), t);
    result.setValue(Vec3f(t[0], t[1], t[2]));
}