Подтвердить что ты не робот

Соответствующее умножение матриц для вращения/перевода

Rotation and Translation about arbitrary point

Чтобы вращать/переводить объект (вращение только вокруг оси z и перевод только в плоскости xy), а не только по отношению к глобальному центру (центру устройства), но и по другим произвольным точкам, я создал алгоритм, который является правильным ( потому что все старшие кодеры, с которыми я обсуждал, считая это правильным), , но занимает много времени, чтобы удалить нежелательный перевод в реализации (алгоритм был создан 4 августа и был реализован в тот же день, с тех пор код был пересмотрен в 15 раз).

Вот реализация http://www.pixdip.com/opengles/transform.php#ALGO1

Строки кода, вызывающие нежелательный перевод, находятся внутри:

private static void updateModel(int upDown, float xAngle, float yAngle, float zAngle) {

и перечислены ниже:

  • Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

  • objX = GLES20Renderer._uBodyCentreMatrix[0];

  • objY = GLES20Renderer._uBodyCentreMatrix[1];

Нежелательный перевод вдоль + Y сохраняется, даже если сделаны следующие изменения:

  • objY = _uBodyCentreMatrix[1] - _uBodyCentre[1];

  • zAngle = 0;

  • ds = 0;

Значение -0.545867f добавляется к координате Y при каждом вызове onDrawFrame() из-за этих полей класса Renderer:

private static final float[] _uBodyCentre = new float[]{-0.019683f, -0.545867f, -0.000409f, 1.0f};

protected static float[] _uBodyCentreMatrix = new float[4];

в http://www.pixdip.com/opengles/transform.php#FIELDS

Мне нужна помощь, чтобы понять, почему происходит этот нежелательный перевод, что именно неправильно с преобразованиями, или это неправильный алгоритм.

Может ли проблема с Gimbal блокироваться?

Пожалуйста, не просите меня выполнять/применять более простые примеры, потому что я подготовил класс Renderer для вращения/перевода о глобальной оси z, и эта новая задача, в которой я участвую, использует тот же класс с небольшой модификацией в updateModel()

(Обратите внимание, что требуемое вращение только о оси z и сдвиге только в плоскости xy)

[API 10- > 15]

В реальном классе Renderer есть два объекта: танковая башня (сопло) и корпус танка, в то время как турель (сопло) имеет нежелательный прямой перевод, тело имеет нежелательный обратный перевод

Apk для перевода/поворота вокруг центра устройства (что легко сделать в opengles 2.0): http://www.pixdip.com/opengles/global.php

Apk для перевода/поворота вокруг произвольных точек (что имеет нежелательный перевод вдоль + Y): http://www.pixdip.com/opengles/local.php

Apk для перевода/вращения вокруг произвольных точек, в которых updateModel() вызывается только 4 раза: http://www.pixdip.com/opengles/limited.php и требуемый код (который должен быть достаточным): http://www.pixdip.com/opengles/code.php

Части объекта (сопло/башня, тело) в настоящее время вращаются вокруг своих центров, а не центра объекта (это _playerCentre), я изменю это позже.

Я попытался продемонстрировать логику http://www.pixdip.com/opengles/images.php

4b9b3361

Ответ 1

[решено] Ошибки с плавающей запятой java были единственной причиной

M = T * я ​​* T [inv]

не приводило к единичной матрице, поэтому вместо использования Matrix.MultiplyMM

Я набираю все умножения между матрицами

Ответ 2

Похоже, проблема такова:

Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

Matrix.multiplyMV - это способ умножить 4-элементный вектор на матрицу 4x4 и сохранить результат в 4-элементном векторе-столбце. В матричной нотации: result = lhs x rhs. Значения элемента resultVector undefined, если элементы resultVector перекрывают элементы lhsMatrix или rhsVector.

Я не думаю, что вы разместили весь код, поэтому я не могу проверить это точно, но, судя по вашему названию '_uBodyCentreMatrix', вы, вероятно, сталкиваетесь с ошибкой, потому что это не 4-элементный вектор-столбец.

Я предполагаю, что "_ModelMatrixBody" - это матрица 4x4, а "_uBodyCentre" - это 4-элементный вектор, иначе это может быть проблематично.

Ответ 3

Вы можете использовать такой метод:

public void rotateToAbritrary(float[] arbitraryPoint, float xAngle, float yAngle, float zAngle) {
    Matrix.translateM(modelMatrix, 0, arbitraryPoint[0], arbitraryPoint[1], arbitraryPoint[2]);
    float max = Math.max(xAngle, Math.max(yAngle, zAngle));
    if(max != 0.0f) Matrix.rotateM(modelMatrix, 0, max, xAngle / max, yAngle / max, zAngle / max);
    Matrix.translateM(modelMatrix, 0, -arbitraryPoint[0], -arbitraryPoint[1], -arbitraryPoint[2]);
}

Как я вижу это, по крайней мере, я оставляю вас на пути к реализации. Я понимаю, что ваш код не страдает блокировкой Gimbal.

Ответ 4

http://tutorialrandom.blogspot.com/2012/08/how-to-rotate-in-3d-using-opengl-proper.html

Я считаю, что это самый простой способ делать вращения без каких-либо привязок к кардану или нечетному переводу. его пример iOS, но я уверен, что его можно легко применить к Android. Также его для трехмерных вращений, но его можно легко применить к 2d, просто не вращаясь вокруг одной из осей.