Move on any surface

I’m so close, but I’m not able to get the orientation corrected. This is my adjusted Body.class from sim-eth.es

package ch.artificials.bg.sim;

import com.simsilica.es.EntityId;
import com.simsilica.mathd.*;

import ch.artificials.bg.es.Position;

public class Body {

    public final EntityId bodyId;

    public Vec3d pos = new Vec3d();
    public Vec3d velocity = new Vec3d();
    public Vec3d acceleration = new Vec3d();
    public double radius = 1;
    public double invMass = 1;
    public AaBBox bounds = new AaBBox(radius);

    public Quatd orientation = new Quatd();
    public volatile DriverControl driver;

    // XXX: experiment
    public Vec3d altPos = new Vec3d();
    public Quatd altOrientation = new Quatd();

    public Body(EntityId bodyId) {
        this.bodyId = bodyId;
    }

    public Body(EntityId bodyId, double x, double y, double z) {
        this.bodyId = bodyId;
        pos.set(x, y, z);
    }

    public void setPosition(Position pos) {
        this.pos.set(pos.getLocation());
        this.orientation.set(pos.getFacing());
    }

    public void integrate(double stepTime) {
        // Integrate velocity
        velocity.addScaledVectorLocal(acceleration, stepTime);

        // Integrate position
        pos.addScaledVectorLocal(velocity, stepTime);
        
        // XXX Trial
        pos.normalizeLocal();
        pos.multLocal(30);
    }
}

The XXX Trial is my change. Radius of my sphere is 30 for the moment. I put the ship initial on (0, 30, 0). So now it runs on one half of a sphere, but because the orientation is not adjusted it get’s slower and slower till it reaches the half of the sphere. Makes sense, because the thrust is in the direction of the body. I think I only need to adjust the x-axis rotation. I wanted to measure the angle between before and after the pos update, I did a toVector3f().clone() on entrance and on exit and then did oldPos.angleBettween(newPos), but the result is always 0.

EDIT: Of course I have to follow this local x axis rotation on client I also do not yet, because that client orientation is the one I would need in the end that thrust points “around” the sphere.

Something I miss here, but I don’t know what exactly. In case somebody sees my mistake I’m happy to hear and learn.

What about oldPos and newPos themselves? Do they look different?

yes they do look different. small difference of course. maybe that is the problem? and the bigger the radius the smaller of course. I tried to get the old pos less frequently (once every 0.5 second) but still the angle was 0. As soon I’m at my computer I’ll try again and post that code so you can see …
but maybe I need a different approach.

EDIT: I’ll try maybe as well quaternion’s lookAt(shipPos, UNIT_X) apply it and then take the cross product. Maybe much better

if we accept that every step is small enough so that velocity.length() * stepTime approximately equals to the corresponding length of an arc of the circle (strictly speaking it is not, so I’m not sure), rotation angle for the step would be

double rotStep = stepTime * velocity.length() / 30;

not sure if this is better approach though

I also thought about using angles instead of move in Z and correct the distance to origin. But it works only my ship does not point in tangential direction but points still in the x/z plane (I will mayb upload a short youtube movie to show).

and because the ship does not bend his nose the thrust vector does neither, so it slows down toward the aequator.

I mean you could move it like you do now, just correct orientation (and thus velocity direction), say, via fromAngleAxis by this angle around its local X axis

Ok I got it :slight_smile: I try this…
But I guess it will end in cumulative errors in the long run

Well, consider stepTime and velocity absolute value fixed. Result is then fixed. Position is calculated independently. Where it will accumulate error then? Edit: you mean direction will have continued less correction than it actually needs, and thus angle will differ from right more and more… yep, point. Well, then it won’t go without some reference it can be corrected against, indeed.
Edit2: in my implementation of orbiting a point I was checking if actual fwd direction (defined by current orientation) is within some epsilon threshold of HALF_PI to vector to the circle center (known vector, coz you have your actual position and sphere center to get this one), and was rotating if it was exceeded. Otherwise I was just moving straight.
Edit3: to clarify the idea


So, here angles are depicted:

  • on frame N: nothing happens to orientation

  • on frame N+i: angle differs from HALF_PI too much (threshold exceeded), so it tries to rotate to look at center (I defined constant rotation speed and used slerp between current orientation and lookAt produced quat looking at center, so it was slow enough not to make it looking at the center straight in that frame, but fast enough to rotate faster than actual angle increased)

  • on frame N+i+j: angle again differs, but this time it’s smaller than needed, so it rotates now to look at point that is opposite to the center (blue vector).
    Not sure that it is the best approach, but it was working for me.

1 Like

Just want to let you know that the facing works when I do this but without the division by 30. But somehow my control component which holds the current speed and facing and the concept of the ship driver, does not apply the new facing to the velocity vector. I have honestly no clue how I could make it work for the moment. So maybe I start simple with a flat map, it was too good to be true.

But thanks a lot to all for the links, hints and suggestions, I learned again new things.

1 Like

Well, I’m particularly interested in this topic, cause I’ll have to implement similar behavior too (someday) anyway, and I’m not that good with sim-eth-es workflow myself yet :slight_smile: Distracted a bit into depths of gradle at the moment. So, either you or I will come back here with something in due course, I think :slight_smile:

1 Like

Same to me with this sim-eth-es it is not the simplest example I saw :slight_smile: I think I have first to find out how that physics really works (more the orientation which I struggle much as it is a local orientation not a world orientation) and where I should do the orientation adjustment, not in the Body.class that is for sure! Maybe in the driver.

But yeah I’m looking forward to solution, no matter if it is me, you or someone else. If I find a solution I let you know and try to provide the needed code snippets.

An ultimate one, i’d say. So much to explore in here. I had fancy time finding out where those bit sizes in console output (when you begin hosting) were coming from, just for instance :slight_smile:

Just one bit more of information, if I do the adjustment in the driver, then for the bullets it seems to work more or less, I just have to store it again in my Control component I have (I made that ship driver a bit more es like).

But in some cases the bullet goes faster and faster, so still not done, but a little bit closer. I think it is because I do not yet that correction you suggest where you look that the vector to the sphere’s origin and the velocity vector are still in a right angle (PI/2).

Further more the first step I made was to turn off up and down, I only can turn left and right with the ship so it stays in a plane (currently x/z plane) or on this sphere :slight_smile:

The ship does not yet work because the clients in put makes the x-Axis rotation back to zero all the time. But first it hast to work for the bullets and rockets I can fire.