A problem with spatial coordinates

/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package SelectUnit.Hominini;

import com.dongbat.walkable.FloatArray;
import com.jme3.bullet.collision.ContactListener;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.GhostControl;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import java.util.ArrayList;
import java.util.List;
import mygame.Main;
import org.dyn4j.geometry.Vector2;
import physicsState.MinieBulletAppState;
import physicsState.dyn4j.BodyControl;
import scenario.scenarioState;
import static scenario.scenarioState.mapGrid3D;

/**
 *
 * @author icyboxs
 */
public class T100Control extends AbstractControl implements PhysicsCollisionListener, ContactListener {

    List<Vector3f> move = new ArrayList<Vector3f>();
    int groupSize = 2;
    Vector3f group = new Vector3f(0, 0, 0);
    int i = 0;
    private Vector3f moveTo = null;
    private float moveSpeed = 5.0f; // 设置移动速度
    Quaternion targetQua = new Quaternion();
    private Vector3f previousGridPosition;
    private int Cellsize = (int) mapGrid3D.getCellsize();

    public ArrayList<Vector3f> Avoid;

    private int CurrentState = 0;
    private int MoveState = 1;
    private int WaitState = 2;



    public void addAvoid(Vector3f v3f) {

        this.Avoid.add(v3f);

    }

    /**
     * @return the CurrentState
     */
    public int getCurrentState() {
        return CurrentState;
    }

    public T100Control() {
        this.Avoid = new ArrayList<>();

    }

    public void setPath(FloatArray floatArray, Vector3f RightClickMapLocation) {

        move.clear();
        i = 0;
        for (int i = 0; i < floatArray.size; i += 2) {
            float x = (float) floatArray.get(i);
            float y = 0.0f;
            float z = (float) floatArray.get(i + 1);

            Vector3f vector = new Vector3f(x, y, z);
            move.add(vector);
        }

    }
    float FOWtime = 0;

    @Override
    protected void controlUpdate(float tpf) {
        if (spatial != null) {


            if (i < move.size() - 1) {


                CurrentState = MoveState;
//                var s=spatial.getUserData("CombatantsUnitNode");
//                System.err.println(s);
                // 获取当前空间位置
                Vector3f currentWorldPosition = spatial.getWorldTranslation();
                // 将世界位置转换为网格坐标
                Vector3f currentGridPosition = new Vector3f((int) currentWorldPosition.x / Cellsize, 0, (int) currentWorldPosition.z / Cellsize);
                // 判断位置是否改变
                FOWtime += tpf;

                if (FOWtime > 0.25) {
                    if (!currentGridPosition.equals(previousGridPosition)) {
                        // 位置已更改,执行相应的操作
                        // ...
                        scenarioState.setFowImag((int) spatial.getLocalTranslation().x, (int) spatial.getLocalTranslation().z, scenarioState.raster);

                        // 更新前一网格坐标
                        previousGridPosition = currentGridPosition;

                    }
                    FOWtime = 0;
                }

                MoveWork(spatial, tpf);

            } else {
                CurrentState = WaitState;
            }

        }
    }

    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {
    }

    @Override
    public void setSpatial(Spatial spatial) {
        super.setSpatial(spatial);

         MinieBulletAppState.bulletAppState.getPhysicsSpace().addCollisionListener(this);
         MinieBulletAppState.bulletAppState.getPhysicsSpace().addContactListener(this);
         
    }

    /**
     * 让物体按照寻路给出的坐标进行移动
     *
     * @param spatial
     */
    protected void MoveWork(Spatial spatial, float tpf) {
        Vector3f currentPoint = spatial.getLocalTranslation();
        Vector3f nextPoint = move.get(i + 1);
        // 计算节点朝下一个点移动的步进
        Vector3f step = nextPoint.subtract(currentPoint).normalizeLocal().multLocal(tpf).multLocal(50f);
        //旋转
        Quaternion rotation = spatial.getLocalRotation();
        targetQua.lookAt(step, new Vector3f(0, 1, 0));
        rotation.nlerp(targetQua, 0.05f);
        //移动
        spatial.setLocalTranslation(currentPoint.add(step));
        // 检查是否已经到达下一个点getLocalTranslation
        float distanceToNextPoint = spatial.getLocalTranslation().distance(nextPoint);
        //System.err.println(distanceToNextPoint);
        if (distanceToNextPoint < 2.5f) {
            // 如果已经到达下一个点,更新当前路径索引
            i++;
        }
    }

    @Override
    public void collision(PhysicsCollisionEvent event) {

//if(event.getNodeB().getParent().getControl(T100Control.class).getCurrentState()==2){
//    Vector3f local = event.getNodeB().getParent().getLocalTranslation().subtract(spatial.getLocalTranslation()).normalize();
//    event.getNodeB().getParent().getControl(T100Control.class).addAvoid(local);
//
//}else if(event.getNodeA().getParent().getControl(T100Control.class).getCurrentState()==2){
//        Vector3f local = event.getNodeA().getParent().getLocalTranslation().subtract(spatial.getLocalTranslation()).normalize();
//        event.getNodeA().getParent().getControl(T100Control.class).addAvoid(local);
//
//
//}
    }

    @Override
    public void onContactEnded(long manifoldId) {

    }

    @Override
    public void onContactProcessed(PhysicsCollisionObject pcoA, PhysicsCollisionObject pcoB, long manifoldPointId) {

        if (((Spatial) pcoB.getUserObject()).getParent().getControl(T100Control.class).getCurrentState() == 2) {
            System.err.println(((Spatial) pcoB.getUserObject()).getParent().getUserData("CombatantsUnitNode").toString());
            Vector3f local = ((Spatial) pcoB.getUserObject()).getParent().getWorldTranslation().subtract(((Spatial) pcoA.getUserObject()).getWorldTranslation()).normalizeLocal();
            System.err.println(local);
            ((Spatial) pcoB.getUserObject()).getParent().move(local.setY(0));
        } else if (((Spatial) pcoA.getUserObject()).getParent().getControl(T100Control.class).getCurrentState() == 2) {
            System.err.println(((Spatial) pcoA.getUserObject()).getParent().getUserData("CombatantsUnitNode").toString());
            Vector3f local = ((Spatial) pcoA.getUserObject()).getParent().getWorldTranslation().subtract(((Spatial) pcoB.getUserObject()).getWorldTranslation()).normalizeLocal();
            System.err.println(local);
            ((Spatial) pcoA.getUserObject()).getParent().move(local.setY(0));

        }
        
    }

    @Override
    public void onContactStarted(long manifoldId) {
    }

}

This code implements exactly how to make the collided target extrude to another location.

    @Override
    public void onContactProcessed(PhysicsCollisionObject pcoA, PhysicsCollisionObject pcoB, long manifoldPointId) {

        if (((Spatial) pcoB.getUserObject()).getParent().getControl(T100Control.class).getCurrentState() == 2) {
            System.err.println(((Spatial) pcoB.getUserObject()).getParent().getUserData("CombatantsUnitNode").toString());
            Vector3f local = ((Spatial) pcoB.getUserObject()).getParent().getWorldTranslation().subtract(((Spatial) pcoA.getUserObject()).getWorldTranslation()).normalizeLocal();
            System.err.println(local);
            ((Spatial) pcoB.getUserObject()).getParent().move(local.setY(0));
        } else if (((Spatial) pcoA.getUserObject()).getParent().getControl(T100Control.class).getCurrentState() == 2) {
            System.err.println(((Spatial) pcoA.getUserObject()).getParent().getUserData("CombatantsUnitNode").toString());
            Vector3f local = ((Spatial) pcoA.getUserObject()).getParent().getWorldTranslation().subtract(((Spatial) pcoB.getUserObject()).getWorldTranslation()).normalizeLocal();
            System.err.println(local);
            ((Spatial) pcoA.getUserObject()).getParent().move(local.setY(0));

        }
        
    }

That’s what I thought at first,
Unit A on the move collides with unit B on standby, calculates the vector of unit A based on the collision information and uses MOVE to move unit B. Theoretically this should work (and it does in practice but there are some problems).

This is me placing the T100Control on 2 Nodes (tanks) and as you can see from the video everything is fine and within normal expectations.
https://youtu.be/f1H7PybxR34

This is me putting the T100Control into multiple Nodes (tanks), from the video you can see that the tanks are “squeezed” very far away? I don’t understand what’s going on, there’s no particular change in the value of local, but after the actual Move() operation the tanks are “squeezed” very far away.
https://youtu.be/ZvHUtnD1rys

If anyone knows what happened, please help me.

java - What are classes, references, and objects? - Stack Overflow

Well I made a conceptual mistake which led to a lot of phenomena that I couldn’t understand.

The description from the linked article made me realise my mistake

((Spatial) pcoA.getUserObject()).getParent().getControl(T100Control.class).equals(this)

I’ve added a judgement to the if to determine that the Control is the Control I need

Is that the line that was the problem or the line you used to fix it?

…because it’s straight up crazy.

This fixes the problem I was having, well in my opinion “it” just looks a bit long :sweat_drops:

Why is it crazy? :face_with_raised_eyebrow:

.equals(this) in any context is already a bad smell. It’s automatically weird and it’s hard to imagine a context where it isn’t.

First: equals is almost certainly not what you want here. It would be super strange for a control to implement .equals() and so this is no different really than ==.

((Spatial) pcoA.getUserObject()).getParent().getControl(T100Control.class) == this

Then there is the fact that you must already know that ‘this’ is a T100Control and so there is no reason to look one up. You already know the spatial to which you are attached so you don’t need to ask the collision spatial for its T100Control just to check to see if you are it. You can just check directly.

((Spatial) pcoA.getUserObject()).getParent() == getSpatial()

You also seem to repeat a lot of the same code over and over for no good reason.

((Spatial) pcoA.getUserObject()).getParent()
((Spatial) pcoB.getUserObject()).getParent()
((Spatial) pcoA.getUserObject()).getParent()
((Spatial) pcoB.getUserObject()).getParent()
((Spatial) pcoA.getUserObject()).getParent()
...all over the place...

Instead of:

Spatial parentA = ((Spatial) pcoA.getUserObject()).getParent();
Spatial parentB = ((Spatial) pcoB.getUserObject()).getParent();
...reuse as needed...

These things do not just make the code ‘prettier’. They make it easier to move around in, easier to read, easier to work with, etc… Also less prone to a silly typo hiding somewhere.

2 Likes

Ok I see what you mean by “crazy”, and yes it is crazy because the code is created on the fly (I write whatever comes to mind), and every time I wake up I have to deal with the weird code again and rethink and rewrite it! …:sweat_smile: :sweat_smile: :sweat_smile: