0

我想根据自己的方向移动一个对象。对象有一个平移向量和一个旋转向量(度)。我可以调用一个方法 move 并给它一个方向和对象应该移动的单位(如果你愿意的话,速度)。如果我给这个方法一个“FORWARD”的方向,而不是它应该在对象当前面对的方向上移动。

我目前有这个代码:

/*
 * MIT License
 * 
 * Copyright (c) 2017 Ralph Niemitz
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package de.ralleytn.engine.lunatic;

import javax.vecmath.Vector3f;

/**
 * Merges rotation with translation and adds translation based on rotation.
 * @author Ralph Niemitz/RalleYTN(ralph.niemitz@gmx.de)
 * @version 1.0.0
 * @since 1.0.0
 */
public interface Movable extends Translatable, Rotatable {

    /**
     * Moves the object into the given direction based on its own rotation.
     * @param direction the direction in which the object should be moved
     * @param units the number of units it should be moved
     * @since 1.0.0
     */
    public default void move(Direction direction, float units) {

        float nUnits = -units;
        Vector3f rotation = this.getRotation();

        if(direction == Direction.LEFT) {

            float rY = (float)Math.toRadians(rotation.y);
            float rZ = (float)Math.toRadians(rotation.z);

            float x = (float)Math.cos(rY) * nUnits;
            float y = (float)Math.sin(rZ) * units;
            float z = (float)Math.sin(rY) * nUnits;

            this.translate(x, y, z);

        } else if(direction == Direction.RIGHT) {

            // float rX = (float)Math.toRadians(rotation.x);
            float rY = (float)Math.toRadians(rotation.y);
            float rZ = (float)Math.toRadians(rotation.z);

            float x = (float)Math.cos(rY) * units;
            float y = (float)Math.sin(rZ) * nUnits;
            float z = (float)Math.sin(rY) * units;

            this.translate(x, y, z);

        } else if(direction == Direction.FORWARD) {

            float rX = (float)Math.toRadians(rotation.x);
            float rY = (float)Math.toRadians(rotation.y - 90.0F);

            float x = (float)Math.cos(rY) * units;
            float y = (float)Math.sin(rX) * nUnits;
            float z = (float)Math.sin(rY) * units;

            this.translate(x, y, z);

        } else if(direction == Direction.BACKWARD) {

            float rX = (float)Math.toRadians(rotation.x);
            float rY = (float)Math.toRadians(rotation.y - 90.0F);

            float x = (float)Math.cos(rY) * nUnits;
            float y = (float)Math.sin(rX) * units;
            float z = (float)Math.sin(rY) * nUnits;

            this.translate(x, y, z);

        } else if(direction == Direction.UP) {

            float rX = (float)Math.toRadians(rotation.x);
            float rZ = (float)Math.toRadians(rotation.z);

            float x = (float)Math.sin(rZ) * nUnits;
            float y = (float)Math.cos(rX) * units;
            float z = (float)Math.sin(rX) * nUnits;

            this.translate(x, y, z);

        } else if(direction == Direction.DOWN) {

            float rX = (float)Math.toRadians(rotation.x);
            float rZ = (float)Math.toRadians(rotation.z);

            float x = (float)Math.sin(rZ) * units;
            float y = (float)Math.cos(rX) * nUnits;
            float z = (float)Math.sin(rX) * units;

            this.translate(x, y, z);
        }
    }
}

它并没有按照我想要的方式工作。我对 3D 还很陌生,所以我没有那么多知识。到目前为止我看到的所有解决方案都是针对 Unity 和 C# 的,这对我没有帮助。

如果这很重要,我正在使用 javax.vecmath 包。

4

1 回答 1

0

有不同的方法可以完成您的要求。

其中之一应该是维护一个前向向量,以及您在 Object 实例中的旋转表示。前向向量应该用vec3(0, 0, 1)初始化;

我不知道是什么Vector3f rotation = this.getRotation();如果它是欧拉角(偏航、俯仰和滚动),您可能应该避免对自己进行三角学并使用一些预定义的函数来计算基于这些角度的旋转矩阵here

您可以在开始时仅从 Rx 和 Ry 开始,并使用一些方法,例如: glRotatef(value, 0, 1, 0);for Ry

glRotatef(value, 1, 0, 0);用于 Rx

现在,每次完成轮换时,您都应该更新这些轮换值。您从旋转矩阵开始,然后将此旋转矩阵应用于您的InitialForwardvector

m_rotation = Matrix4f.identity().rotateX(Rx).rotateY(Ry);
m_forward  = m_rotation * vec3(0, 0, 1);

现在当你判断是时候翻译了

vec3 translationVector = speed * m_forward;
this.translate(translationVector.x, translationVector.y, translationVector.z);

如果您想向左走,您可以通过将 90° 添加到旋转矩阵的偏航角来计算左矢量。我不确定这是否是您有时在视频游戏中想要的,最好只在 XZ 平面上移动。

Matrix4f rotation = Matrix4f.identity().rotateX(Rx /* maybe 0 */).rotateY(Ry + 1.57);
m_left = m_rotation * vec3(0, 0, 1);

您还可以计算您的初始左向量,删除上面的代码并使用相同的旋转矩阵但应用于您的左向量,您将获得更好的性能。试着让你的 initLeftVector 与你的 initialForward 垂直。

vec3 initialLeft = vec3(1, 0, 0);
m_left = m_rotation * initialLeft;
于 2017-11-27T08:10:47.270 回答