Quaternionf and mathematic java

82 Views Asked by At

I need help with this. I'm trying to make the position and rotation of my objects relative to their parents and thus almost infinitely. I managed to make 1 parent have 1 child and the rotation and position change according to the parent, and I can also directly change the child and it still stays where it should. Now I have a problem: if I add 1 child to that child and rotate the first child, the second child rotates as it should but doesn't move to the correct position to maintain relativity with the others. I'll leave the code and examples here.

create:

        main = new Cube(0, 0, 0, 0, 0, 0, 4, 0.2f, 2);

        Cube leg1 = new Cube(-0.95f, -0.1f, 0.4f, 0, 0, 0, 0.2f, 1, 0.2f);
        Cube leg2 = new Cube(0.95f, -0.1f, 0.4f, 0, 0, 0, 0.2f, 1, 0.2f);
        Cube leg3 = new Cube(-0.95f, -0.1f, -0.4f, 0, 0, 0, 0.2f, 1, 0.2f);
        Cube leg4 = new Cube(0.95f, -0.1f, -0.4f, 0, 0, 0, 0.2f, 1, 0.2f);

        main.addChild(leg1);
        main.addChild(leg2);
        main.addChild(leg3);
        main.addChild(leg4);

        Cube leg1Child = new Cube(0, -0.5f, 0, 0, 0, 0, 0.2f, 1, 0.2f);
        leg1.addChild(leg1Child);
        main. Spawn(location);

Here are the examples that work well, and at the end, the one that works poorly.

rotate main "x:0, y:0, z:90" rotate leg1. error with child

As you can see, the child of "leg1" doesn't stay where it should. Now I'll leave you the complete code of the class.

package net.kokoricraft.deepshark.objects;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Transformation;
import org.joml.Quaternionf;
import org.joml.Vector3f;

import java.util.ArrayList;
import java.util.List;

public class Cube {

    private float local_position_x, local_position_y, local_position_z;
    private float local_rotation_x, local_rotation_y, local_rotation_z;
    private float local_scale_x, local_scale_y, local_scale_z;
    private float global_rotation_x, global_rotation_y, global_rotation_z;
    private float global_position_x, global_position_y, global_position_z;
    private ItemDisplay display;
    private final List<Cube> childs = new ArrayList<>();
    private Cube parent;

    public Cube(float local_position_x, float local_position_y, float local_position_z, float local_rotation_x, float local_rotation_y, float local_rotation_z, float local_scale_x, float local_scale_y, float local_scale_z) {
        this.local_position_x = local_position_x;
        this.local_position_y = local_position_y;
        this.local_position_z = local_position_z;
        this.local_rotation_x = local_rotation_x;
        this.local_rotation_y = local_rotation_y;
        this.local_rotation_z = local_rotation_z;
        this.local_scale_x = local_scale_x;
        this.local_scale_y = local_scale_y;
        this.local_scale_z = local_scale_z;

        Bukkit.broadcastMessage("x:"+local_position_x+" y:"+local_position_y+" z:"+local_position_z);
    }

    public void spawn(Location origin){
        World world = origin.getWorld();
        if(world == null) return;

        display = world.spawn(origin, ItemDisplay.class);

        float position_x = local_position_x;
        float position_y = local_position_y;
        float position_z = local_position_z;

        if(parent != null){
            position_x += parent.local_position_x;
            position_y += parent.local_position_y;
            position_z += parent.local_position_z;
        }

        setTranslation(position_x, position_y, position_z);

        Transformation transformation = display.getTransformation();
        transformation.getScale().set(local_scale_x, local_scale_y, local_scale_z);

        display.setItemStack(new ItemStack(Material.PLAYER_HEAD));
        display.setTransformation(transformation);

        for (Cube child : childs) {
            child.spawn(origin);
        }
    }

    public void setTranslation(float x, float y, float z){
        Transformation transformation = display.getTransformation();
        transformation.getTranslation().set(x, y, z);
        display.setTransformation(transformation);
    }

    public void rotate(float rotation_x, float rotation_y, float rotation_z){
        local_rotation_x = rotation_x;
        local_rotation_y = rotation_y;
        local_rotation_z = rotation_z;
        update();
    }

    public void addChild(Cube cube){
        childs.add(cube.setParent(this));
    }

    public Cube setParent(Cube parent){
        this.parent = parent;
        return this;
    }

    public void update() {
        if (parent != null) {
            global_rotation_x = local_rotation_x + parent.global_rotation_x;
            global_rotation_y = local_rotation_y + parent.global_rotation_y;
            global_rotation_z = local_rotation_z + parent.global_rotation_z;
            global_position_x = local_position_x + parent.global_position_x;
            global_position_y = local_position_y + parent.global_position_y;
            global_position_z = local_position_z + parent.global_position_z;
        } else {
            global_rotation_x = local_rotation_x;
            global_rotation_y = local_rotation_y;
            global_rotation_z = local_rotation_z;
            global_position_x = local_position_x;
            global_position_y = local_position_y;
            global_position_z = local_position_z;
        }

        float rotation_x = (float)Math.toRadians(global_rotation_x);
        float rotation_y = (float)Math.toRadians(global_rotation_y);
        float rotation_z = (float)Math.toRadians(global_rotation_z);

        Quaternionf quaternionf = new Quaternionf();
        quaternionf.rotateXYZ(rotation_x, rotation_y, rotation_z);

        Vector3f rotatePosition = new Vector3f(global_position_x, global_position_y, global_position_z);

        if(parent != null){
            Quaternionf parentQuaternionf = new Quaternionf();
            parentQuaternionf.rotateXYZ((float) Math.toRadians(parent.global_rotation_x), (float) Math.toRadians(parent.global_rotation_y), (float) Math.toRadians(parent.global_rotation_z));
            parentQuaternionf.transform(rotatePosition);
        }

        Transformation transformation = display.getTransformation();


        transformation.getTranslation().set(rotatePosition.x, rotatePosition.y, rotatePosition.z);

        transformation.getLeftRotation().set(quaternionf);

        display.setTransformation(transformation);

        for (Cube child : childs) {
            child.update();
        }
    }

    public List<Cube> getChilds(){
        return childs;
    }
}

I tried many options, but I don't have enough knowledge to achieve it. I would like that, regardless of how many sub-children each cube has, it remains where it should. The rotation works well no matter how many children they have, but the problem is the position, which changes with "setTranslation".

0

There are 0 best solutions below