2016-06-11 5 views
1

Пару недель назад я решил создать свой собственный простой игровой движок. Я следил за несколькими учебниками онлайн, и я смотрел много видео, и до сих пор я получил очень хороший движок. Но у меня есть одна проблема. Когда я поворачиваю или масштабирую объект, кажется, что его центр - верхний левый угол экрана, а не его реальный центр. Например, когда я поворачиваю объект, он вращается вокруг левого края экрана, и когда я его масштабирую, масштабируется в направлении угла экрана или вдалеке от угла экрана. Вот мой код:Почему моя матрица вращения дает дополнительный перевод?

сетки класса

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 } 
    }); 
} 

} 

Сцена Класс

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 Класс

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]) 
    ); 
} 

} 

Пожалуйста, посмотрите на эти фотографии, если вы еще не» знать я имею в виду.

Изображение # 1:

Still Triangle

Изображение # 2:

Triangle Rotated 30 Degrees

Вы видите, как она вращается вокруг угла вместо его центра? Спасибо за ваши усилия, пытаясь помочь!

ответ

0

Это обычно происходит, когда вы делаете трансформации без переустановки вашего объекта до Происхождение, прежде чем воздействовать на него. Помните, что порядок Матрицы имеет значение. Вращения происходят относительно Происхождения, поэтому, если ваш объект не находится на Origin, он будет вращаться странно.

Попробуйте повернуть его, переведя его на (0,0,0). Затем примените нужный перевод к треугольнику (это перевести в начало, повернуть, вернуться в исходное положение).

Надеюсь, это поможет.

EDIT

В общем, если вы хотите, чтобы повернуть многоугольник Arround фиксированной точке вы должны перевести многоугольник таким образом, что искомая точка находится в (0,0,0). Затем выполните поворот и, наконец, вернитесь в исходное положение.

Скажем, у вас есть треугольник с вершиной (1,1), (3,1) и (2,3). Если вы хотите, чтобы вращаться вокруг центра этого треугольника (который (2,2)) вы должны:

  1. Вычтите (2,2) из каждой вершины (делая (2,2) начало координат)
  2. Затем поверните на нужный угол
  3. Добавить (2,2) каждой вершине, возвращаясь в исходное положение.

Эти же принципы применяются к 3 размерам.

+1

Спасибо, я добавил маленький перевод, и он отлично работал. –

+1

Подождите, на самом деле, неважно, когда я устанавливаю форму в начало координат, она по-прежнему вращается вокруг, она фиксирует только часть части фигуры. Если вы не понимаете, что я пытаюсь сказать, я опубликую еще одну картину того, как это должно быть. –

+0

Думаю, я тебя понимаю. Вы должны сделать '(0,0,0)' неподвижную точку, где вы хотите повернуть arround. Если вы хотите, чтобы один из углов был такой фиксированной точкой, сделайте эту вершину '(0,0,0)' и переведите остальные соответственно. Если вы хотите, чтобы центр треугольника фиксировал ту же точку для него (вычислите центр, сделайте начало центра, поверните, вернитесь в позицию) – DarkCygnus