简体   繁体   English

为什么我的旋转矩阵会提供额外的翻译?

[英]Why is my rotation matrix giving an extra translation?

A couple weeks ago I decided to make my own simple 3d game engine. 几周前,我决定制作自己的简单3D游戏引擎。 I've followed a couple tutorials online, and I looked at many videos, and so far, I've gotten I pretty good engine. 我在网上看了几个教程,看了很多视频,到目前为止,我已经得到了很好的引擎。 But I have one problem. 但我有一个问题。 When I rotate or scale an object, it seems that its center is the top-left corner of the screen instead of its real center. 当我旋转或缩放对象时,它的中心似乎是屏幕的左上角而不是它的真实中心。 For example, when I rotate an object, it rotates around the left edge of the screen, and when I scale it, is scales towards the corner of the screen or away from the corner of the screen. 例如,当我旋转一个物体时,它会围绕屏幕的左边缘旋转,当我缩放它时,它会朝向屏幕的角落或远离屏幕的角落。 Here's my code: 这是我的代码:

Mesh Class 网格类

package com.cub.cubefront.mesh;

import com.cub.cubefront.math.Matrix4f;
import com.cub.cubefront.math.Vector3f;

public class Mesh {

    private Vector3f[] verts;
    private Vector3f center;

    private double rotX = 0;
    private double rotY = 0;
    private double rotZ = 0;

    private double scaleX = 1;
    private double scaleY = 1;
    private double scaleZ = 1;

    private double translateX = 0;
    private double translateY = 0;
    private double translateZ = 0;

public Mesh(int arg0) {
    verts = new Vector3f[arg0];
}

public Vector3f getVertexAt(int arg0) {
    return verts[arg0 - 1];
}

public Vector3f[] getVerticies() {
    return verts;
}

public int getVerticiesCount() {
    return verts.length;
}

public void setVertexAt(int arg0, Vector3f arg1) {
    verts[arg0 - 1] = arg1;
}

public void setRotationPoint(Vector3f arg0) {
    this.center = arg0;
}

public Vector3f getRotationPoint() {
    return center;
}

public Vector3f getCenter() {
    int arg0 = verts.length;
    double centerX = 0;
    double centerY = 0;
    double centerZ = 0;
    for (int i = 0; i < arg0; i++) {
        centerX += verts[i].getX();
        centerY += verts[i].getY();
        centerZ += verts[i].getZ();
    }
    return new Vector3f((float)(centerX / arg0), (float)(centerY / arg0), (float)(centerZ / arg0));
}

public void rotateX(double arg0) {
    this.rotX += Math.toRadians(arg0);
}

public void setRotationX(double arg0) {
    this.rotX = Math.toRadians(arg0);
}

public Matrix4f getXRotationAsMatrix() {
    return new Matrix4f(new double[][] { // YZ rotation matrix (X)
        { 1, 0, 0, 0 },
        { 0, Math.cos(rotX), Math.sin(rotX), 0 },
        { 0, -Math.sin(rotX), Math.cos(rotX), 0 },
        { 0, 0, 0, 1 }
    });
}

public Matrix4f getZRotationAsMatrix() {
    return new Matrix4f(new double[][] { // XY rotation matrix (Z)
        { Math.cos(rotZ), -Math.sin(rotZ), 0, 0 },
        { Math.sin(rotZ), Math.cos(rotZ), 0, 0 },
        { 0, 0, 1, 0 },
        { 0, 0, 0, 1 }
    });
}

public void rotateY(double arg0) {
    this.rotY += Math.toRadians(arg0);
}

public void setRotationY(double arg0) {
    this.rotY = Math.toRadians(arg0);
}

public Matrix4f getYRotationAsMatrix() {
    return new Matrix4f(new double[][] { // XZ rotation matrix (Y)
        { Math.cos(rotY), 0, Math.sin(rotY), 0 },
        { 0, 1, 0, 0 },
        { -Math.sin(rotY), 0, Math.cos(rotY), 0},
        { 0, 0, 0, 1 }
    });
}

public void setRotationZ(double arg0) {
    this.rotZ = Math.toRadians(arg0);
}

public void rotateZ(double arg0) {
    this.rotZ += Math.toRadians(arg0);
}

public Matrix4f getRotation() {
    return getZRotationAsMatrix().multiply(getXRotationAsMatrix()).multiply(getYRotationAsMatrix());
}

public void setScaleX(double arg0) {
    this.scaleX = arg0;
}

public void scaleX(double arg0) {
    this.scaleX += arg0;
}

public double getScaleX() {
    return scaleX;
}

public void setScaleY(double arg0) {
    this.scaleY = arg0;
}

public void scaleY(double arg0) {
    this.scaleY += arg0;
}

public double getScaleY() {
    return scaleY;
}

public void setScaleZ(double arg0) {
    this.scaleZ = arg0;
}

public void scaleZ(double arg0) {
    this.scaleZ += arg0;
}

public double getScaleZ() {
    return scaleZ;
}

public void setScale(double arg0) {
    setScaleX(arg0);
    setScaleY(arg0);
    setScaleZ(arg0);
}

public void setScale(double[][] arg0) {
    this.scaleX = arg0[0][0];
    this.scaleY = arg0[1][1];
    this.scaleZ = arg0[2][2];
}

public void setScale(Matrix4f arg0) {
    this.scaleX = arg0.getValueAt(0, 0);
    this.scaleY = arg0.getValueAt(1, 1);
    this.scaleZ = arg0.getValueAt(2, 2);
}

public void scale(double arg0) {
    scaleX(arg0);
    scaleY(arg0);
    scaleZ(arg0);
}

public Matrix4f getScale() {
    return new Matrix4f(new double[][] {
            { getScaleX(), 0, 0, 0 },
            { 0, getScaleY(), 0, 0 },
            { 0, 0, getScaleZ(), 0 },
            { 0, 0, 0, 1 }
    });
}

public void translateX(double arg0) {
    this.translateX += arg0;
}

public void translateY(double arg0) {
    this.translateY += arg0;
}

public void translateZ(double arg0) {
    this.translateZ += arg0;
}

public Matrix4f getTranslation() {
    return new Matrix4f(new double[][] {
        { 1, 0, 0, translateX },
        { 0, 1, 0, translateY },
        { 0, 0, 1, translateZ },
        { 0, 0, 0, 1 }
    });
}

}

Scene Class 场景类

package com.cub.cubefront;

import com.cub.cubefront.graphics.Bitmap;
import com.cub.cubefront.input.InputHandler;
import com.cub.cubefront.math.Matrix4f;
import com.cub.cubefront.math.Vector2f;
import com.cub.cubefront.math.Vector3f;
import com.cub.cubefront.mesh.Camera;
import com.cub.cubefront.mesh.Mesh;

public class Scene extends Bitmap {

private Camera defaultCam;

public InputHandler input = new InputHandler();

public Scene() {
    super(MainEngine.getWidth(), MainEngine.getHeight());
    defaultCam = new Camera();
}

public void update() { }

public void start() { }

public void render() { }

public void render(Mesh arg0) {
    Matrix4f trans = arg0.getRotation().multiply(arg0.getScale().multiply(arg0.getTranslation()));
    for (int i = 1; i < arg0.getVerticiesCount()+1; i++) { // Depth: Manipulate x and y with z
        Vector3f v1 = trans.transform(arg0.getVertexAt(i));
        for (int n = 1; n < i; n++) {
            Vector3f v2 = trans.transform(arg0.getVertexAt(n));
            drawLine(
                new Vector2f((v1.getX()), (v1.getY())),
                new Vector2f((v2.getX()), (v2.getY()))
            );
        }
    }
}

public void clear() {
    for (int i = 0; i < pixels.length; i++) {
        pixels[i] = 0;
    }
}

public Camera getCamera() {
    return defaultCam;
}

public void setCamera(Camera defaultCam) {
    this.defaultCam = defaultCam;
}

} }

Matrix4f Class Matrix4f类

package com.cub.cubefront.math;

public class Matrix4f {

private double[][] values;

public Matrix4f() {
    values = new double[4][4];
    setValues();
}

public Matrix4f(double[][] arg0) {
    setValues(arg0);
}

private Matrix4f setValues() {
    values[0][0] = 1;  values[0][1] = 0;  values[0][2] = 0;  values[0][3] = 0;
    values[1][0] = 0;  values[1][1] = 1;  values[1][2] = 0;  values[1][3] = 0;
    values[2][0] = 0;  values[2][1] = 0;  values[2][2] = 1;  values[2][3] = 0;
    values[3][0] = 0;  values[3][1] = 0;  values[3][2] = 0;  values[3][3] = 1;
    return this;
}

public Matrix4f multiply(Matrix4f arg0) {
    double res[][] = new double[4][4];
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            for (int k = 0; k < 4; k++) {
                res[i][j] += values[i][k] * arg0.getValueAt(k, j);
            }
        }
    }

    return new Matrix4f(res);
}

public double[][] getValues() {
    return values;
}

public double getValueAt(int arg0, int arg1) {
    return values[arg0][arg1];
}

public void setValues(double[][] arg0) {
    this.values = arg0;
}

public void setValueAt(int arg0, int arg1, double arg2) {
    values[arg0][arg1] = arg2;
}

public Vector3f transform(Vector3f arg0) {
    return new Vector3f(
        (float)(arg0.getX() * values[0][0] + arg0.getY() * values[1][0] + arg0.getZ() * values[2][0]),
        (float)(arg0.getX() * values[0][1] + arg0.getY() * values[1][1] + arg0.getZ() * values[2][1]),
        (float)(arg0.getY() * values[0][2] + arg0.getY() * values[1][2] + arg0.getZ() * values[2][2])
    );
}

}

Please look at these pictures if you still don't know what I mean. 如果你还不知道我的意思,请看这些图片。

Picture #1: 图片1:

Still Triangle 还是三角形

Picture #2: 图片#2:

Triangle Rotated 30 Degrees 三角旋转30度

Do you see how it rotates around the corner instead of its center? 你看到它是如何围绕角落而不是它的中心旋转的吗? Thanks for your effort in trying to help! 感谢您努力提供帮助!

This usually happens when you make Transformations without reseting your object to Origin before affecting it. 这种情况通常发生在您进行转换而不将对象重置为Origin之后才会影响它。 Remember that Matrix order matters. 请记住,Matrix订单很重要。 Rotations take place relative to the Origin, so if your object is not on Origin then it will rotate oddly. 旋转相对于原点发生,因此如果您的对象不在原点上,那么它将奇怪地旋转。

Try rotating it after translating it to (0,0,0) . 在将其翻译为(0,0,0)后尝试旋转它。 Then apply the desired translation to the triangle (That is translate to origin, rotate, return to original position). 然后将所需的平移应用于三角形(即转换为原点,旋转,返回原始位置)。

Hope it helps. 希望能帮助到你。

EDIT 编辑

In general if you want to rotate a Polygon arround a fixed point you should translate the polygon in such way that the desired point is in (0,0,0) . 通常,如果要围绕固定点旋转多边形,则应该以所需点(0,0,0)方式平移多边形。 Then procede with rotation and finally return to original position. 然后继续旋转,最后返回原始位置。

Say you have a Triangle with vertex (1,1) , (3,1) and (2,3) . 假设你有一个带顶点(1,1)(3,1)(2,3)的三角形。 If you want to rotate around the center of that triangle (which is (2,2) ) you should: 如果你想围绕该三角形的中心 (即(2,2) )旋转,你应该:

  1. Substract (2,2) from each vertex (making (2,2) the origin) 从每个顶点减去(2,2) (使(2,2)原点)
  2. Then rotate the desired angle 然后旋转所需的角度
  3. Add (2,2) to each vertex, returning to original position. 向每个顶点添加(2,2) ,返回原始位置。

This same principles apply to 3 Dimensions. 同样的原则适用于3维度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM