#opengl #matrix #position #axis #opentk
#opengl #матрица #положение #ось #opentk
Вопрос:
Редактировать: хорошо, теперь я написал код, полностью интуитивно понятный, и вот результат:
http://i.imgur.com/x5arJE9.jpg
Куб находится на 0,0,0
Как вы можете видеть, положение камеры отрицательное по оси z, предполагая, что я просматриваю вдоль положительной оси z, которая не совпадает. (fw отрицательный)
Также цвета куба предполагают, что я нахожусь на положительной оси z, глядя в отрицательном направлении. Также положительная ось x находится справа (в пространстве моделей)
Углы вычисляются следующим образом:
public virtual Vector3 Right
{
get
{
return Vector3.Transform(Vector3.UnitX, Rotation);
}
}
public virtual Vector3 Forward
{
get
{
return Vector3.Transform(-Vector3.UnitZ, Rotation);
}
}
public virtual Vector3 Up
{
get
{
return Vector3.Transform(Vector3.UnitY, Rotation);
}
}
Вращение — это кватернион.
Так создаются матрицы представления и модели:
public virtual Matrix4 GetMatrix()
{
Matrix4 translation = Matrix4.CreateTranslation(Position);
Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
return translation * rotation;
}
Проекция:
private void SetupProjection()
{
if(GameObject != null)
{
AspectRatio = GameObject.App.Window.Width / (float)GameObject.App.Window.Height;
projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)((Math.PI * Fov) / 180), AspectRatio, ZNear, ZFar);
}
}
Умножение матрицы:
public Matrix4 GetModelViewProjectionMatrix(Transform model)
{
return model.GetMatrix()* Transform.GetMatrix() * projectionMatrix;
}
Шейдер:
[Shader vertex]
#version 150 core
in vec3 pos;
in vec4 color;
uniform float _time;
uniform mat4 _modelViewProjection;
out vec4 vColor;
void main() {
gl_Position = _modelViewProjection * vec4(pos, 1);
vColor = color;
}
Матрицы OpenTK транспонируются, таким образом, изменяется порядок умножения.
Есть идеи, почему все оси / местоположения перепутаны?
Конец редактирования. Оригинальное сообщение:
Взгляните на это изображение: http://i.imgur.com/Cjjr8jz.jpg
Как вы можете видеть, в то время как прямой вектор (камеры) положителен по оси z, а красный куб находится на отрицательной оси x,
float[] points = {
// position (3) Color (3)
-s, s, z, 1.0f, 0.0f, 0.0f, // Red point
s, s, z, 0.0f, 1.0f, 0.0f, // Green point
s, -s, z, 0.0f, 0.0f, 1.0f, // Blue point
-s, -s, z, 1.0f, 1.0f, 0.0f, // Yellow point
};
(кубы создаются в геометрическом шейдере вокруг этих точек)
положение камеры x кажется перевернутым. Другими словами, если я увеличу положение камеры вдоль ее локальной оси x, она переместится влево, и наоборот.
Я передаю матрицу преобразования следующим образом:
if (DefaultAttributeLocations.TryGetValue("modelViewProjectionMatrix", out loc))
{
if (loc >= 0)
{
Matrix4 mvMatrix = Camera.GetMatrix() * projectionMatrix;
GL.UniformMatrix4(loc, false, ref mvMatrix);
}
}
Метод GetMatrix() выглядит следующим образом:
public virtual Matrix4 GetMatrix()
{
Matrix4 translation = Matrix4.CreateTranslation(Position);
Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
return translation * rotation;
}
И матрица проекции:
private void SetupProjection()
{
AspectRatio = Window.Width / (float)Window.Height;
projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)((Math.PI * Fov)/180), AspectRatio, ZNear, ZFar);
}
Я не вижу, что я делаю неправильно :/
Ответ №1:
Это немного сложно определить из кода, но я полагаю, это потому, что в OpenGL вектор движения камеры вперед по умолчанию отрицательный вдоль оси Z — ваш положительный, что означает, что вы смотрите на модель сзади. Вот почему координата X кажется инвертированной.
Комментарии:
1. Ну, что бы я ни пытался, какая-то ось всегда кажется инвертированной. Я думаю, что в реализации OpenTK Matrix4 есть что-то странное. Я собираюсь обновить это в ближайшее время.
2. Хм… ну, единственное, что я могу придумать, это то, что OpenTK Matrix4 хранится иначе, чем OpenGL (OpenTK — это строка-мажор, OpenGL — столбец-мажор). Но ваши преобразования выглядят хорошо. Может быть, попробуйте немного перетасовать их, посмотреть, что это дает…
3. Если вы используете матрицы, состоящие из строк, то вам нужно сообщить OpenGL, что передаваемые вами матрицы являются матрицами, состоящими из строк. Посмотрите, например, на третий параметр glUniformMatrix4fv. Также, как сказал Весан, вектор движения вперед по умолчанию для камеры равен (0, 0, -1). Это означает, что вы не можете использовать одну и ту же функцию LookAt для камеры и ваших обычных объектов, если ваши обычные объекты используют (0, 0, 1) в качестве направления вперед. Вы можете создать свою проекционную матрицу так, чтобы камера смотрела вниз по положительной оси z. Это позволит вам использовать одну и ту же функцию поиска для всего.
Ответ №2:
Хотя этому вопросу несколько лет, я все еще хотел бы внести свой вклад.
Причина, по которой вы сталкиваетесь с этой ошибкой, заключается в том, что матрицы OpenTK являются основными по строкам. Все это на самом деле означает, что вам нужно выполнить всю математику матрицы в обратном порядке. Например, матрица преобразования будет умножена следующим образом:
public static Matrix4 CreateTransformationMatrix(Vector3 position, Quaternion rotation, Vector3 scale)
{
return Matrix4.CreateScale(scale) *
Matrix4.CreateFromQuaternion(rotation) *
Matrix4.CreateTranslation(position);
}
Это относится к любой матрице, поэтому, если вы используете Vector3 вместо Quaternion для вашего вращения, это будет выглядеть следующим образом:
public static Matrix4 CreateTransformationMatrix(Vector3 position, Vector3 rotation, Vector3 scale)
{
return Matrix4.CreateScale(scale) *
Matrix4.CreateRotationZ(rotation.Z) *
Matrix4.CreateRotationY(rotation.Y) *
Matrix4.CreateRotationX(rotation.X) *
Matrix4.CreateTranslation(position);
}
Обратите внимание, что ваш вершинный шейдер все равно будет умножен следующим образом:
void main()
{
gl_Position = projection * view * transform * vec4(position, 1.0f);
}
Я надеюсь, что это поможет!