Example #1
0
void RigidBody::CreateBody()
{
    if (!impl->world || impl->body || !ParentEntity())
        return;
    
    CheckForPlaceableAndTerrain();
    
    CreateCollisionShape();
    
    btVector3 localInertia;
    float m;
    int collisionFlags;
    
    impl->GetProperties(localInertia, m, collisionFlags);
    
    impl->body = new btRigidBody(m, impl, impl->shape, localInertia);
    // TEST: Adjust the threshold of when to sleep the object - for reducing network bandwidth.
//    impl->body->setSleepingThresholds(0.2f, 0.5f); // Bullet defaults are 0.8 and 1.0.
    impl->body->setUserPointer(this);
    impl->body->setCollisionFlags(collisionFlags);
    impl->world->BulletWorld()->addRigidBody(impl->body, (short)collisionLayer.Get(), (short)collisionMask.Get());
    impl->body->activate();
    
    UpdateGravity();
}
Example #2
0
void GPlayer::Step(float dt)
{
    CCPoint oldVelocity = velocity;
    CCPoint oldPosition = GetPlayerPosition();

    CCPoint pos = sprite->getPosition();
    pos = pos + velocity;
    sprite->setPosition(pos);

    if(applyGravity)
    	velocity = velocity + gravity;

    if( oldVelocity.y == 0.0 && velocity.y != 0.0 && state == RUN) {
        state = JMP1;
        //CCLog("set player state JMP1");
    }

    //check and set gravity
    UpdateGravity();

    //velocity and gravity have the same direction

    if( (oldPosition.y <= gravity_line_y && pos.y > gravity_line_y) ||
        (oldPosition.y > gravity_line_y && pos.y <= gravity_line_y) ) {
        SwitchGravity();
        JumpDown();
        CCLog("flip gravity!");
    }else if(oldVelocity.y * velocity.y <= 0.0 && velocity.y * gravity.y > 0.0) {
    	//CCLog("player's old velocity.y %f new velocity.y %f)", oldVelocity.y, velocity.y);
        JumpDown();
    }

    //CCLog("player step position(%f, %f) velocity(%f, %f) gravity(%f, %f) state %d",
    //		pos.x, pos.y, velocity.x, velocity.y, gravity.x, gravity.y, state);
}
Example #3
0
void RigidBody::SetGravityOverride(const Vector3& gravity)
{
    if (gravity != gravityOverride_)
    {
        gravityOverride_ = gravity;
        UpdateGravity();
        MarkNetworkUpdate();
    }
}
Example #4
0
void RigidBody::SetUseGravity(bool enable)
{
    if (enable != useGravity_)
    {
        useGravity_ = enable;
        UpdateGravity();
        MarkNetworkUpdate();
    }
}
Example #5
0
void RigidBody::AttributesChanged()
{
    if (impl->disconnected)
        return;
    
    bool isShapeTriMeshOrConvexHull = (shapeType.Get() == TriMesh || shapeType.Get() == ConvexHull);
    bool bodyRead = false;
    bool meshRequested = false;

    // Create body now if does not exist yet
    if (!impl->body)
        CreateBody();
    // If body was not created (we do not actually have a physics world), exit
    if (!impl->body)
        return;
    
    if (mass.ValueChanged() || collisionLayer.ValueChanged() || collisionMask.ValueChanged())
    {
        // Read body to the world in case static/dynamic classification changed, or if collision mask changed
        ReaddBody();
        bodyRead = true;
    }
    
    if (friction.ValueChanged())
        impl->body->setFriction(friction.Get());
    
    if (rollingFriction.ValueChanged())
        impl->body->setRollingFriction(rollingFriction.Get());
    
    if (restitution.ValueChanged())
        impl->body->setRestitution(friction.Get());
    
    if (linearDamping.ValueChanged() || angularDamping.ValueChanged())
         impl->body->setDamping(linearDamping.Get(), angularDamping.Get());
    
    if (linearFactor.ValueChanged())
        impl->body->setLinearFactor(linearFactor.Get());
    
    if (angularFactor.ValueChanged())
        impl->body->setAngularFactor(angularFactor.Get());
    
    if (shapeType.ValueChanged() || size.ValueChanged())
    {
        if (shapeType.Get() != impl->cachedShapeType || !size.Get().Equals(impl->cachedSize))
        {
            // If shape does not involve mesh, can create it directly. Otherwise request the mesh
            if (!isShapeTriMeshOrConvexHull)
            {
                CreateCollisionShape();
                impl->cachedShapeType = shapeType.Get();
                impl->cachedSize = size.Get();
            }
            // If shape type has changed from TrimMesh <--> ConvexHull refresh the mesh shape.
            else if (shapeType.Get() != impl->cachedShapeType)
            {
                RequestMesh();
                meshRequested = true;
            }
            // If size changed but no reload of mesh shape was done, update its scale.
            else if (!size.Get().Equals(impl->cachedSize))
                UpdateScale();
        }
    }
    
    // Request mesh if its id changes
    if (collisionMeshRef.ValueChanged() && isShapeTriMeshOrConvexHull && !meshRequested)
        RequestMesh();
    
    // Readd body to the world in case phantom or kinematic classification changed
    if (!bodyRead && (phantom.ValueChanged() || kinematic.ValueChanged()))
        ReaddBody();
    
    if (drawDebug.ValueChanged())
    {
        bool enable = drawDebug.Get();
        if (impl->body)
        {
            int collisionFlags = impl->body->getCollisionFlags();
            if (enable)
                collisionFlags &= ~btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT;
            else
                collisionFlags |= btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT;
            impl->body->setCollisionFlags(collisionFlags);
        }
        
        // Refresh PhysicsWorld's knowledge of debug-enabled rigidbodies
        if (impl->world)
        {
            if (enable)
                impl->world->debugRigidBodies_.Insert(this);
            else
                impl->world->debugRigidBodies_.Erase(this);
        }
    }
    
    if (linearVelocity.ValueChanged() && !impl->disconnected)
    {
        impl->body->setLinearVelocity(linearVelocity.Get());
        impl->body->activate();
    }
    
    if (angularVelocity.ValueChanged() && !impl->disconnected)
    {
        impl->body->setAngularVelocity(DegToRad(angularVelocity.Get()));
        impl->body->activate();
    }
    
    if (useGravity.ValueChanged())
        UpdateGravity();
}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementTank::ProcessMovement(const float deltaTime)
{ 
	FUNCTION_PROFILER( gEnv->pSystem, PROFILE_GAME );

	m_netActionSync.UpdateObject(this);

	CryAutoCriticalSection lk(m_lock);

	CVehicleMovementBase::ProcessMovement(deltaTime);

	if (!(m_actorId && m_isEnginePowered))
	{
		IPhysicalEntity* pPhysics = GetPhysics();

		if (m_latFriction != 1.3f)
			SetLatFriction(1.3f);

		if (m_axleFriction != m_axleFrictionMax)
			UpdateAxleFriction(0.f, false, deltaTime);

		m_action.bHandBrake = 1;
		m_action.pedal = 0;
		m_action.steer = 0;
		pPhysics->Action(&m_action, 1);
		return;
	}

	IPhysicalEntity* pPhysics = GetPhysics();
	MARK_UNUSED m_action.clutch;

	Matrix34 worldTM( m_PhysPos.q );
	worldTM.AddTranslation( m_PhysPos.pos );

	const Matrix34 invWTM = worldTM.GetInvertedFast();

	Vec3 localVel = invWTM.TransformVector(m_PhysDyn.v);
	Vec3 localW = invWTM.TransformVector(m_PhysDyn.w);
	float speed = m_PhysDyn.v.len();
	float speedRatio = min(1.f, speed/m_maxSpeed);

	float actionPedal = abs(m_movementAction.power) > 0.001f ? m_movementAction.power : 0.f;        

	// tank specific:
	// avoid steering input around 0.5 (ask Anton)
	float actionSteer = m_movementAction.rotateYaw;
	float absSteer = abs(actionSteer);
	float steerSpeed = (absSteer < 0.01f && abs(m_currSteer) > 0.01f) ? m_steerSpeedRelax : m_steerSpeed;

	if (steerSpeed == 0.f)
	{
		m_currSteer =	(float)sgn(actionSteer);
	}
	else
	{ 
		if (m_movementAction.isAI)
		{
			m_currSteer = actionSteer;
		}
		else
		{
			m_currSteer += min(abs(actionSteer-m_currSteer), deltaTime*steerSpeed) * sgn(actionSteer-m_currSteer);        
		}
	}
	Limit(m_currSteer, -m_steerLimit, m_steerLimit);  

	if (abs(m_currSteer) > 0.0001f) 
	{
		// if steering, apply full throttle to have enough turn power    
		actionPedal = (float)sgn(actionPedal);

		if (actionPedal == 0.f) 
		{
			// allow steering-on-teh-spot only above maxReverseSpeed (to avoid sudden reverse of controls)
			const float maxReverseSpeed = -1.5f;
			actionPedal = max(0.f, min(1.f, 1.f-(localVel.y/maxReverseSpeed)));

			// todo
			float steerLim = 0.8f;
			Limit(m_currSteer, -steerLim*m_steerLimit, steerLim*m_steerLimit);
		}
	}

	if (!pPhysics->GetStatus(&m_vehicleStatus))
		return;

	int currGear = m_vehicleStatus.iCurGear - 1; // indexing for convenience: -1,0,1,2,..

	UpdateAxleFriction(m_movementAction.power, true, deltaTime);
	UpdateSuspension(deltaTime);   	

	float absPedal = abs(actionPedal);  

	// pedal ramping   
	if (m_pedalSpeed == 0.f)
		m_currPedal = actionPedal;
	else
	{
		m_currPedal += deltaTime * m_pedalSpeed * sgn(actionPedal - m_currPedal);  
		m_currPedal = clamp_tpl(m_currPedal, -absPedal, absPedal);
	}

	// only apply pedal after threshold is exceeded
	if (currGear == 0 && fabs_tpl(m_currPedal) < m_pedalThreshold) 
		m_action.pedal = 0;
	else
		m_action.pedal = m_currPedal;

	// change pedal amount based on damages
	float damageMul = 0.0f;
	{
		if (m_movementAction.isAI)
		{
			damageMul = 1.0f - 0.30f * m_damage; 
			m_action.pedal *= damageMul;
		}
		else
		{
			// request from Sten: damage shouldn't affect reversing so much.
			float effectiveDamage = m_damage;
			if(m_action.pedal < -0.1f)
				effectiveDamage = 0.4f * m_damage;

			m_action.pedal *= GetWheelCondition();
			damageMul = 1.0f - 0.7f*effectiveDamage; 
			m_action.pedal *= damageMul;
		}
	}

	// reverse steering value for backward driving
	float effSteer = m_currSteer * sgn(actionPedal);   

	// update lateral friction  
	float latSlipMinGoal = 0.f;
	float latFricMinGoal = m_latFricMin;

	if (abs(effSteer) > 0.01f && !m_movementAction.brake)
	{
		latSlipMinGoal = m_latSlipMin;

		// use steering friction, but not when countersteering
		if (sgn(effSteer) != sgn(localW.z))
			latFricMinGoal = m_latFricMinSteer;
	}

	Interpolate(m_currentSlipMin, latSlipMinGoal, 3.f, deltaTime);   

	if (latFricMinGoal < m_currentFricMin)
		m_currentFricMin = latFricMinGoal;
	else
		Interpolate(m_currentFricMin, latFricMinGoal, 3.f, deltaTime);

	float fractionSpeed = min(1.f, max(0.f, m_avgLateralSlip-m_currentSlipMin) / (m_latSlipMax-m_currentSlipMin));
	float latFric = fractionSpeed * (m_latFricMax-m_currentFricMin) + m_currentFricMin;

	if ( m_movementAction.brake && m_movementAction.isAI )
	{
		// it is natural for ai, apply differnt friction value while handbreaking
		latFric = m_latFricMax;
	}

	if (latFric != m_latFriction)
	{ 
		SetLatFriction(latFric);    
	}      

	const static float maxSteer = gf_PI/4.f; // fix maxsteer, shouldn't change  
	m_action.steer = m_currSteer * maxSteer;  

	if (m_steeringImpulseMin > 0.f && m_wheelContactsLeft != 0 && m_wheelContactsRight != 0)
	{  
		const float maxW = 0.3f*gf_PI;
		float steer = abs(m_currSteer)>0.001f ? m_currSteer : 0.f;    
		float desired = steer * maxW; 
		float curr = -localW.z;
		float err = desired - curr; // err>0 means correction to right 
		Limit(err, -maxW, maxW);

		if (abs(err) > 0.01f)
		{ 
			float amount = m_steeringImpulseMin + speedRatio*(m_steeringImpulseMax-m_steeringImpulseMin);

			// bigger correction for relaxing
			if (desired == 0.f || (desired*curr>0 && abs(desired)<abs(curr))) 
				amount = m_steeringImpulseRelaxMin + speedRatio*(m_steeringImpulseRelaxMax-m_steeringImpulseRelaxMin);

			float corr = -err * amount * m_PhysDyn.mass * deltaTime;

			pe_action_impulse imp;
			imp.iApplyTime = 0;      
			imp.angImpulse = worldTM.GetColumn2() * corr;
			pPhysics->Action(&imp, THREAD_SAFE);
		}    
	}

	m_action.bHandBrake = (m_movementAction.brake) ? 1 : 0;	

	if (currGear > 0 && m_vehicleStatus.iCurGear < m_currentGear) 
	{
		// when shifted down, disengage clutch immediately to avoid power/speed dropdown
		m_action.clutch = 1.f;
	}

	pPhysics->Action(&m_action, 1);

	if (Boosting())  
		ApplyBoost(speed, 1.2f*m_maxSpeed*GetWheelCondition()*damageMul, m_boostStrength, deltaTime);  

	if (m_wheelContacts <= 1 && speed > 5.f)
	{
		ApplyAirDamp(DEG2RAD(20.f), DEG2RAD(10.f), deltaTime, THREAD_SAFE);
		UpdateGravity(-9.81f * 1.4f);
	}

	if (m_netActionSync.PublishActions( CNetworkMovementStdWheeled(this) ))
		CHANGED_NETWORK_STATE(m_pVehicle,  eEA_GameClientDynamic );
}
Example #7
0
void RigidBody::AddBodyToWorld()
{
    if (!physicsWorld_)
        return;

    URHO3D_PROFILE(AddBodyToWorld);

    if (mass_ < 0.0f)
        mass_ = 0.0f;

    if (body_)
        RemoveBodyFromWorld();
    else
    {
        // Correct inertia will be calculated below
        btVector3 localInertia(0.0f, 0.0f, 0.0f);
        body_ = new btRigidBody(mass_, this, shiftedCompoundShape_, localInertia);
        body_->setUserPointer(this);

        // Check for existence of the SmoothedTransform component, which should be created by now in network client mode.
        // If it exists, subscribe to its change events
        smoothedTransform_ = GetComponent<SmoothedTransform>();
        if (smoothedTransform_)
        {
            SubscribeToEvent(smoothedTransform_, E_TARGETPOSITION, URHO3D_HANDLER(RigidBody, HandleTargetPosition));
            SubscribeToEvent(smoothedTransform_, E_TARGETROTATION, URHO3D_HANDLER(RigidBody, HandleTargetRotation));
        }

        // Check if CollisionShapes already exist in the node and add them to the compound shape.
        // Do not update mass yet, but do it once all shapes have been added
        PODVector<CollisionShape*> shapes;
        node_->GetComponents<CollisionShape>(shapes);
        for (PODVector<CollisionShape*>::Iterator i = shapes.Begin(); i != shapes.End(); ++i)
            (*i)->NotifyRigidBody(false);

        // Check if this node contains Constraint components that were waiting for the rigid body to be created, and signal them
        // to create themselves now
        PODVector<Constraint*> constraints;
        node_->GetComponents<Constraint>(constraints);
        for (PODVector<Constraint*>::Iterator i = constraints.Begin(); i != constraints.End(); ++i)
            (*i)->CreateConstraint();
    }

    UpdateMass();
    UpdateGravity();

    int flags = body_->getCollisionFlags();
    if (trigger_)
        flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
    else
        flags &= ~btCollisionObject::CF_NO_CONTACT_RESPONSE;
    if (kinematic_)
        flags |= btCollisionObject::CF_KINEMATIC_OBJECT;
    else
        flags &= ~btCollisionObject::CF_KINEMATIC_OBJECT;
    body_->setCollisionFlags(flags);
    body_->forceActivationState(kinematic_ ? DISABLE_DEACTIVATION : ISLAND_SLEEPING);

    if (!IsEnabledEffective())
        return;

    btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
    world->addRigidBody(body_, (short)collisionLayer_, (short)collisionMask_);
    inWorld_ = true;
    readdBody_ = false;

    if (mass_ > 0.0f)
        Activate();
    else
    {
        SetLinearVelocity(Vector3::ZERO);
        SetAngularVelocity(Vector3::ZERO);
    }
}