# Simulating linear inertia

I have an aabb (player) which can move dynamically - to get acceleration I am saving the previous previous position (through prevPrevPos, prevPos and pos acceleration will be calculated). Now I have a tiny aabb which could fall on that player aabb (collision friction is a thing in my system). How would I simulate inertia? My current approach is not quite right in some scenarios - on collision I pass the player's acceleration (change direction) into the tiny aabb's velocity and set it's position in such a way that it sticks on the top. In the next iteration the tiny aabb would then calculate new velocity (taking friction into account) to slowly deaccelerate and move away from the original point of impact until it stops and completely sticks on top of the player (if player is moving with a constant velocity).

Problem: tiny aabb is falling on the player moving with constant velocity. Tiny aabb is now slowly moving to the edge of the player and eventually falls off - however, it is then moving away from the player, as I used the negative acceleration of the player to calculate a somewhat relative movement. I also needed to do a if friction == 0 do nothing, so my approach has some flaws and it kind of feels like I need to take a lot of special cases into consideration to make it run correctly...

What would be common approaches for inertia?

Here is my inertia method: it is called on collision (main update loop would be: first call update method of particle then check for collisions (where inertia takes place))

public void inertia(BedrockParticle particle, Entity entity, @Nullable Vector3d now)
{
if(this.collisionDrag==0)
{
return;
}

Vector3d entitySpeed = new Vector3d((entity.posX - entity.prevPosX), (entity.posY - entity.prevPosY), (entity.posZ - entity.prevPosZ));

double prevPrevPosX = EntityTransformationUtils.getPrevPrevPosX(entity);
double prevPrevPosY = EntityTransformationUtils.getPrevPrevPosY(entity);
double prevPrevPosZ = EntityTransformationUtils.getPrevPrevPosZ(entity);

Vector3d prevEntitySpeed = new Vector3d(entity.prevPosX-prevPrevPosX, entity.prevPosY-prevPrevPosY, entity.prevPosZ-prevPrevPosZ);

/*if(Math.round((prevEntitySpeed.x-entitySpeed.x)*1000D) != 0 || Math.round((prevEntitySpeed.y-entitySpeed.y)*1000D) != 0 || Math.round((prevEntitySpeed.z-entitySpeed.z)*1000D) != 0)
{
particle.dragFactor = 0;
}*/

/* for first collision from the inertial system of the particle it is acceleration from zero to current velocity */
if(!particle.entityCollisionTime.containsKey(entity))
{
prevEntitySpeed.scale(0);
}
else
{
/* stick the particle on top of the entity */
if(now == null)
{
particle.position.x += entitySpeed.x;
particle.position.z += entitySpeed.z;
}
else
{
now.x += entitySpeed.x;
now.z += entitySpeed.z;
}
}

particle.speed.x += Math.round((prevEntitySpeed.x-entitySpeed.x)*1000D)/200D; //scale it up so it gets more noticable
particle.speed.y += Math.round((prevEntitySpeed.y-entitySpeed.y)*1000D)/200D;
particle.speed.z += Math.round((prevEntitySpeed.z-entitySpeed.z)*1000D)/200D;
}


and here is particle update method (it is not a strict physics system, I know, I didn't write the basis of it)

    public void update(BedrockEmitter emitter)
{
this.prevRotation = this.rotation;
this.prevPosition.set(this.position);

this.setupMatrix(emitter);

if (!this.manual)
{
if(this.realisticCollisionDrag && Math.round(this.speed.x*10000) == 0 && Math.round(this.speed.y*10000) == 0 && Math.round(this.speed.z*10000) == 0)
{
this.dragFactor = 0;
this.speed.scale(0);
}

float rotationAcceleration = this.rotationAcceleration / 20F -this.rotationDrag * this.rotationVelocity;
this.rotationVelocity += rotationAcceleration / 20F;
this.rotation = this.initialRotation + this.rotationVelocity * this.age;

/* Position */
if (this.relativeDirection && this.age == 0)
{
emitter.rotation.transform(this.speed);
}

if (this.relativeAcceleration)
{
emitter.rotation.transform(this.acceleration);
}

Vector3f drag = new Vector3f(this.speed);

drag.scale(-(this.drag + this.dragFactor));

if (this.gravity)
{
this.acceleration.y -= 9.81;
}

this.acceleration.scale(1 / 20F);

Vector3f speed0 = new Vector3f(this.speed);
speed0.x *= this.accelerationFactor.x;
speed0.y *= this.accelerationFactor.y;
speed0.z *= this.accelerationFactor.z;

if (this.relativePosition || this.relativeRotation)
{
this.matrix.transform(speed0);
}

this.position.x += speed0.x / 20F;
this.position.y += speed0.y / 20F;
this.position.z += speed0.z / 20F;
}