Я разрабатываю аналог OpenGL.Таким образом, у меня есть модель, вид и матрицы проекций.
Масштабирование и вращение идеально работают без перевода.Но когда я применяю перевод к объекту и пытаюсь повернуть его снова - он вращается вокруг источника мира.
Я знаю, что операции преобразования должны происходить в следующем порядке: масштабирование -> вращение -> перевод.Но я не понимаю, как это сделать только с одной матрицей (моделью).
Итак, как мне сделать это правильно?Должен ли я использовать 3 матрицы?
Моя работа с матрицами:
for (int i = 0; i < vertices.Count; ++i)
{
float[,] vertexCoords = { { vertices[i].SX }, { vertices[i].SY }, { vertices[i].SZ }, { vertices[i].SW } };
var modelViewMatrix = MatrixMultiplier.MultiplyMatrix(camera.ViewMatrix, shape.ModelMatrix);
var eyeCoordinates = MatrixMultiplier.MultiplyMatrix(modelViewMatrix, vertexCoords);
var clipCoordinates = MatrixMultiplier.MultiplyMatrix(camera.ProjectionMatrix, eyeCoordinates);
var ndc = new float[,] {
{ clipCoordinates[0, 0] / clipCoordinates[3, 0] },
{ clipCoordinates[1, 0] / clipCoordinates[3, 0] },
{ clipCoordinates[2, 0] / clipCoordinates[3, 0] },
{ clipCoordinates[3, 0]}
};
var windowCoordinates = new float[,] {
{ 640 / 2 * ndc[0, 0] + (640 / 2) },
{ 360 / 2 * ndc[1, 0] + (360 / 2) },
{ (50 - (-50)) / 2 * ndc[2, 0] + (50 + (-50)) / 2 },
{ ndc[3, 0]}
};
SetNewCoordinatesToPoint(vertices[i], windowCoordinates);
}
Пример алгоритма вращения:
private void RotateZ(MCommonPrimitive shape, double angle)
{
double rads = angle * Math.PI / 180.0;
float[,] rotateZ = {
{ (float)Math.Cos(rads), -(float)Math.Sin(rads), 0, 0 },
{ (float)Math.Sin(rads), (float)Math.Cos(rads), 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 1 }
};
shape.ModelMatrix = MatrixMultiplier.MultiplyMatrix(rotateZ, shape.ModelMatrix);
}
MatrixMultiplier:
public static class MatrixMultiplier
{
public static float[,] MultiplyMatrix(float[,] a, float[,] b)
{
float[,] c = null;
if (a.GetLength(1) == b.GetLength(0))
{
c = new float[a.GetLength(0), b.GetLength(1)];
for (int i = 0; i < c.GetLength(0); i++)
{
for (int j = 0; j < c.GetLength(1); j++)
{
c[i, j] = 0;
for (int k = 0; k < a.GetLength(1); k++) // OR k<b.GetLength(0)
c[i, j] = c[i, j] + a[i, k] * b[k, j];
}
}
}
else
{
Console.WriteLine("\n Number of columns in First Matrix should be equal to Number of rows in Second Matrix.");
Console.WriteLine("\n Please re-enter correct dimensions.");
throw new ArithmeticException("Number of columns in First Matrix should be equal to Number of rows in Second Matrix");
}
return c;
}
}