Android: проблемы с поворотом камеры в GLES 20

Я переместил свою камеру (mViewMatrix) в трехмерное пространство, на 15° к каждому углу x,y,z (при всех углах 0° у меня нет проблем с вращением камеры!)

Все объекты в трехмерном пространстве в порядке (показано в правой нижней части экрана).

Хорошо, теперь я хочу повернуть камеру вокруг оси X. Объекты в правом нижнем углу должны перемещаться снизу вверх с правой стороны.

Но... из-за изменения угла обзора камеры в 15°... объекты движутся не только вниз с правой стороны... они также немного двигаются справа налево.

Я думаю, что я должен изменить вектор с:

Matrix.setRotateM(mViewMatrix, 0, 15, 0, 1, 0);

чтобы:

Matrix.setRotateM(mViewMatrix, 0, 15, cameraVector.x, cameraVector.y, cameraVector.z);

... или что-то.

Это то, что я сделал (я знаю, что должен использовать матрицу поворота, но здесь я разместил простой код, только для удобства чтения):

Matrix.setIdentityM(mViewMatrix, 0);
Matrix.translateM(mViewMatrix, 0, 0, 0, -8);
Matrix.setRotateM(mViewMatrix, 0, 15 + angle, 1, 0, 0);
Matrix.setRotateM(mViewMatrix, 0, 15, 0, 1, 0);
Matrix.setRotateM(mViewMatrix, 0, 15, 0, 0, 1);

Было бы хорошо, если бы кто-то мог опубликовать работающий простой демонстрационный код, потому что я пробовал 5 дней, и я не знаю, как это исправить (я много тестировал).

2 ответа

Решение

На самом деле вы не можете вращать камеру в OpenGL. Вместо этого вы должны перемещать / вращать объекты вокруг. Вам необходимо применить матрицы модель / вид / проекция к каждому визуализируемому объекту. Вам не нужно вычислять их все самостоятельно, вы можете использовать android.graphics.matrix. Вы использовали это в своем коде, но с неправильным методом. Чтобы повернуть камеру, вы должны использовать метод.

Matrix.setLookAtM(float rm[], int rmOffset, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)

Тем не менее, вам необходимо указать координаты точки, в которой ваша камера должна быть центрирована. К счастью, найти координаты такой точки легко, вам просто нужно немного тригонометрии и 3 строки кода:

centerX = eyeX + ( float ) Math.cos( Math.toRadians( pitch ) ) * ( float ) Math.cos( Math.toRadians( yaw ) );  
centerY = eyeY - ( float ) Math.sin( Math.toRadians( pitch ) );  
centerZ =eyeZ + ( float ) Math.cos( Math.toRadians( pitch ) ) * ( float ) Math.sin( Math.toRadians( yaw ) );  

Math.cos (двойной угол) и Math.sin(двойной угол) принимают углы в радианах, поэтому вы должны преобразовать их в радианы, используя Math.toRadians (двойной угол). Эти функции возвращают значения типа double, поэтому вам нужно привести их к плавающему типу, потому что функции класса Matrix принимают значения с плавающей точкой в ​​качестве координат.

Вот весь рабочий код:

float pitch = 0;
float yaw   = 90;
float roll  = -90;

lookX   = eyeX + ( float ) Math.cos( Math.toRadians( pitch ) ) * ( float ) Math.cos( Math.toRadians( yaw ) );
lookY   = eyeY - ( float ) Math.sin( Math.toRadians( pitch ) );
lookZ   = eyeZ + ( float ) Math.cos( Math.toRadians( pitch ) ) * ( float ) Math.sin( Math.toRadians( yaw ) );

upX = (float) Math.cos(Math.toRadians( roll ));
upY = (float) -Math.sin(Math.toRadians( roll )); 

Matrix.setIdentityM(mViewMatrix, 0);
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
Другие вопросы по тегам