Вращайте куб и отслеживайте его стороны

Я пытался решить проблему, чтобы повернуть воксель (3D-куб) и отслеживать стороны после его вращения.

Возьмем, к примеру, это изображение. введите здесь описание изображения

После поворота мне нужно знать, где находятся стороны после. Например, если бы я повернул этот куб по оси Z на 90 градусов, Y и X поменялись бы местами.

Это серверный мод 3D-воксельной игры, написанный на Unity. Таким образом, методы/утилиты Unity также доступны. Но опять же, это серверная часть и мод, поэтому у меня нет доступа к самой сетке или объекту, я могу только сказать ему повернуть x, y или z, и мне нужно выполнить логику, основанную на окончательном вращении. Если кто-то может указать мне общее направление или показать мне метод, который может это сделать, я был бы признателен. Спасибо!

РЕДАКТИРОВАТЬ: вращение сохраняется в вращении x, y, z


person JBurlison    schedule 26.06.2019    source источник
comment
Как сохранить вращение?   -  person Nico Schertler    schedule 26.06.2019
comment
Он принимает значения x, y, z с плавающей запятой, но беспокоится только о 90, 180, 270 оборотах по каждой оси.   -  person JBurlison    schedule 26.06.2019
comment
Если вы хотите узнать правильное лицо, трансформируйте (1, 0, 0) с помощью вращения и посмотрите, куда оно указывает. То же самое для других лиц.   -  person Nico Schertler    schedule 26.06.2019
comment
Самого объекта у меня нет, трансформировать нечего. У меня есть позиция блока Vector3Int и возможность придать моду API вращение x, y, z. Мне нужен метод, чтобы повернуть блок и узнать, на какой стороне находится Z +, например, после поворота.   -  person JBurlison    schedule 26.06.2019
comment
Итак, эти три целых числа являются углами Эйлера? Затем вы можете преобразовать свой вектор с помощью них.   -  person Nico Schertler    schedule 26.06.2019
comment
Да, это углы Эйлера. Не могли бы вы показать мне пример?   -  person JBurlison    schedule 26.06.2019
comment
Например, поворот вектора (x, y, z) на 90° вокруг оси x равен (x, -z, y). Повторите это столько раз, сколько требует ваша ротация. Затем продолжите с двумя другими осями. Вращение вокруг оси Y равно (z, y, -x), а вращение вокруг оси Z равно (-y, x, z).   -  person Nico Schertler    schedule 26.06.2019
comment
учитывая, что он всегда будет знать, где находится вверх относительно оригинала, вы сможете легко отслеживать данную сторону.   -  person BugFinder    schedule 26.06.2019
comment
Может ли кто-нибудь привести пример того, как я могу это сделать? Я не знаком с самим Unity. Я корпоративный разработчик, лол. Я только изучаю этот материал.   -  person JBurlison    schedule 26.06.2019
comment
github. com/JBurlison/Pandaros.Settlers/blob/master/ Вот ссылка на то, где мне нужно сделать ротацию. Я сделал лучшее предположение, но не работает.   -  person JBurlison    schedule 26.06.2019


Ответы (1)


Возможно, это немного «глупое» решение, но я бы просто сохранил соответствующие имена сторон в массиве и выполнил сдвиг соответствующего значения для каждого шага на 90 ° вокруг определенной оси.

Итак, скажем, например. в состоянии по умолчанию у вас есть

0 : X_l
1 : Z_u
2 : Y_l
3 : Z_l
4 : Y_u
5 : X_u

тогда на самом деле все, что вам нужно знать, это матрица изменений для одного шага 90 ° для каждой оси и каждого направления (+ или -):

Ось X

                     positive step              negative step

original index    0 | 1 | 2 | 3 | 4 | 5      0 | 1 | 2 | 3 | 4 | 5
new index         0 | 2 | 3 | 4 | 1 | 5      0 | 4 | 1 | 2 | 1 | 0

Ось Y

                     positive step              negative step

original index    0 | 1 | 2 | 3 | 4 | 5      0 | 1 | 2 | 3 | 4 | 5
new index         3 | 0 | 2 | 5 | 4 | 1      1 | 5 | 2 | 0 | 4 | 3

Ось Z

                     positive step              negative step

original index    0 | 1 | 2 | 3 | 4 | 5      0 | 1 | 2 | 3 | 4 | 5
new index         4 | 1 | 0 | 3 | 5 | 2      2 | 1 | 5 | 3 | 0 | 4

Я реализовал это в классе Cube вроде

// The possible names of your cube sides
public enum CubeSideName
{
    X_l,
    X_u,
    Y_l,
    Y_u,
    Z_l,
    Z_u
}

// This stores the relationship between one certain
// position (Front,Back,Top,Bottom,Right,Left)
// and a cube side (x_l, x_u, y_l, y_u, z_l, z_u)
[Serializable]
public struct CubeSidePair
{
    // For the example I used GameObjects with according names
    // instead of GameObjects you could also simply have a string ID or another enum 
    // for the name of the according position
    public GameObject GameObject;
    public CubeSideName Name;
}

[Serializable]
public class Cube
{
    // This stores which position (Front,Back,Top,Bottom,Right,Left)
    // is currently taken by which cube side (x_l, x_u, y_l, y_u, z_l, z_u)
    public CubeSidePair[] CubeSidesPair = new CubeSidePair[6];

    public Vector3Int Rotation
    {
        get { return _rotation; }
        set
        {
            UpdateRotation(value);
        }
    }

    // This is actually just for making it visual
    private readonly Dictionary<CubeSideName, Color> colors = new Dictionary<CubeSideName, Color>(6)
    {
        {CubeSideName.X_u, Color.blue },
        {CubeSideName.X_l, Color.cyan },

        {CubeSideName.Y_u, Color.red },
        {CubeSideName.Y_l, Color.magenta },

        {CubeSideName.Z_u,Color.green },
        {CubeSideName.Z_l,Color.yellow }
    };

    [Header("Debug only")]
    [SerializeField] private Vector3Int _rotation;

    public void Reset()
    {
        _rotation = Vector3Int.zero;

        CubeSidesPair[0].Name = CubeSideName.X_l;
        CubeSidesPair[1].Name = CubeSideName.Z_u;
        CubeSidesPair[2].Name = CubeSideName.Y_l;
        CubeSidesPair[3].Name = CubeSideName.Z_l;
        CubeSidesPair[4].Name = CubeSideName.Y_u;
        CubeSidesPair[5].Name = CubeSideName.X_u;

        UpdateColors();
    }

    // Here all the magic happens
    private void UpdateRotation(Vector3Int newRotaion)
    {
        // get difference to current rotation
        var newRotationInput = newRotaion - _rotation;

        // Go in 90° steps around the according axis
        // untilt he rotation is done
        while (newRotationInput != Vector3Int.zero)
        {
            // For each rotation step just take the index matrices from before
            // and use them to perform an array shift
            if (newRotationInput.x < 0)
            {
                // do negative X rotation
                var temp = CubeSidesPair[1].Name;
                CubeSidesPair[1].Name = CubeSidesPair[2].Name;
                CubeSidesPair[2].Name = CubeSidesPair[3].Name;
                CubeSidesPair[3].Name = CubeSidesPair[4].Name;
                CubeSidesPair[4].Name = temp;

                newRotationInput.x += 90;
            }
            else if (newRotationInput.x > 0)
            {
                // do positive X rotation
                var temp = CubeSidesPair[4].Name;
                CubeSidesPair[4].Name = CubeSidesPair[3].Name;
                CubeSidesPair[3].Name = CubeSidesPair[2].Name;
                CubeSidesPair[2].Name = CubeSidesPair[1].Name;
                CubeSidesPair[1].Name = temp;

                newRotationInput.x -= 90;
            }
            else if (newRotationInput.y < 0)
            {
                // do negative Y rotation
                var temp = CubeSidesPair[1].Name;
                CubeSidesPair[1].Name = CubeSidesPair[0].Name;
                CubeSidesPair[0].Name = CubeSidesPair[3].Name;
                CubeSidesPair[3].Name = CubeSidesPair[5].Name;
                CubeSidesPair[5].Name = temp;

                newRotationInput.y += 90;
            }
            else if (newRotationInput.y > 0)
            {
                // do positive Y rotation
                var temp = CubeSidesPair[3].Name;
                CubeSidesPair[3].Name = CubeSidesPair[0].Name;
                CubeSidesPair[0].Name = CubeSidesPair[1].Name;
                CubeSidesPair[1].Name = CubeSidesPair[5].Name;
                CubeSidesPair[5].Name = temp;

                newRotationInput.y -= 90;
            }
            else if (newRotationInput.z < 0)
            {
                // do negative Z rotation
                var temp = CubeSidesPair[2].Name;
                CubeSidesPair[2].Name = CubeSidesPair[0].Name;
                CubeSidesPair[0].Name = CubeSidesPair[4].Name;
                CubeSidesPair[4].Name = CubeSidesPair[5].Name;
                CubeSidesPair[5].Name = temp;

                newRotationInput.z += 90;
            }
            else if (newRotationInput.z > 0)
            {
                // do positive Z rotation
                var temp = CubeSidesPair[4].Name;
                CubeSidesPair[4].Name = CubeSidesPair[0].Name;
                CubeSidesPair[0].Name = CubeSidesPair[2].Name;
                CubeSidesPair[2].Name = CubeSidesPair[5].Name;
                CubeSidesPair[5].Name = temp;

                newRotationInput.z -= 90;
            }
        }

        _rotation = newRotaion;

        UpdateColors();
    }

    // Just for the visual
    private void UpdateColors()
    {
        foreach (var cubeSide in CubeSidesPair)
        {
            var renderer = cubeSide.GameObject.GetComponent<Renderer>();

            renderer.material.color = colors[cubeSide.Name];
        }
    }
}

И вот как я использовал это для демонстрации (см. внизу):

public class CubeController : MonoBehaviour
{
    public Cube Cube;

    private void Awake()
    {
        // Initial setup
        Cube.Reset();
    }

    private void Update()
    {
        var multiplier = 90;

        if (Input.GetKey(KeyCode.LeftShift))
        {
            multiplier = -90;
        }

        if (Input.GetKeyDown(KeyCode.X))
        {
            Cube.Rotation += Vector3Int.right * multiplier;
        }
        else if (Input.GetKeyDown(KeyCode.Y))
        {
            Cube.Rotation += Vector3Int.up * multiplier;
        }
        else if (Input.GetKeyDown(KeyCode.Z))
        {
            Cube.Rotation += new Vector3Int(0, 0, 1) * multiplier;
        }
    }
}

введите здесь описание изображения

Я надеюсь, что я мог визуализировать идею немного;)

Конечно, я вращал только пошагово, но он должен работать так же, если вводить фиксированное вращение, например

Cube.Rotation = new Vector3(-90, 180, 270);

Однако вы можете изменить порядок, в котором выполняются повороты.

person derHugo    schedule 26.06.2019