0
\$\begingroup\$

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.add(drag);
        this.acceleration.scale(1 / 20F);
        this.speed.add(this.acceleration);

        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;
    }

    if (this.lifetime >= 0 &&
        (this.age >= this.lifetime || (this.age>=this.expireAge && this.expireAge!=0)) )
    {
        this.dead = true;
    }

    this.age ++;
}
\$\endgroup\$
5
  • \$\begingroup\$ It sounds like you already have linear inertia implemented via a Verlet integrator. If you have two objects with no acceleration, one whose previous and current pos are equal and one where they're not, the first will stay stationary forever and the second will move at a constant velocity until acted on by some other acceleration or collision. That's linear inertia. So the problem you're solving sounds more like how to stick together objects by friction and separate them. Can you clarify how the code for accelerating the tiny AABB works? Do you zero the acceleration when it's no longer carried? \$\endgroup\$
    – DMGregory
    Mar 3, 2021 at 12:43
  • \$\begingroup\$ The thing is that the system I am working with is not really a strict physics simulation but I am trying to implement more and more physics options. So in short: the acceleration of the particle (tiny aabb) is not set to zero in the update loop. The acceleration of the player on collision gets directly added to the speed of the particle. I will try to update my question to make it a little bit more clear. Everything else like stopping suddenly or moving in a circle looks fine but when particles fall off the player because the friction is not so high they are moving away from the player... \$\endgroup\$
    – Chryfi
    Mar 3, 2021 at 13:11
  • \$\begingroup\$ To clarify first: when a block falls on a moving block with constant velocity and the friction is not high enough to keep it on the top it would eventually fall off (if the distance from impact point to the edge is tiny enough) but then it would move in the same direction as the bigger block, right? \$\endgroup\$
    – Chryfi
    Mar 3, 2021 at 13:13
  • \$\begingroup\$ It would move in the same direction of its velocity the instant before separation. If that velocity was pointing backward, it will continue moving backward, even if the object it fell on was travelling forward. It sounds like you may have a bug in your code, and you should include your code in your question so we can help you debug it. \$\endgroup\$
    – DMGregory
    Mar 3, 2021 at 14:22
  • \$\begingroup\$ Alright, I added the important methods. Last question regarding the physics: do you mean the global velocity or the velocity relative to the moving player? Because one would point in the direction of the player since it is moving with it and the other would be point backwards as it is slowly moving off the player due to inertia. \$\endgroup\$
    – Chryfi
    Mar 3, 2021 at 14:32

0

You must log in to answer this question.

Browse other questions tagged .