Мащабиране, завъртане, преместване w. матрици в openGl ES 2.0

Работя с OpenGL ES 2.0 и се опитвам да изградя моя обектен клас с някои методи за завъртане/превеждане/мащабиране.

Просто настройвам обекта си в 0,0,0 и след това го премествам на желаната позиция на екрана. По-долу са моите методи за отделно преместване. След това стартирам buildObjectModelMatrix, за да предам всички матрици в един objectMatrix, така че мога да взема върховете и да ги умножа с моя modelMatrix/objectMatrix и да го изобразя след това.

Това, което смятам за правилно, трябва да умножа матриците си в този ред:

[мащаб]x[въртене]x[превод]

->

[temp]x[превод]

->

[objectMatrix]

Намерих малко литература. Може би ще го получа след няколко минути, ако искам, ще го актуализирам.

Начало на Android 3D

https://gamedev.stackexchange.com/questions/16719/what-is-the-correct-order-to-multiply-scale-rotation-and-translation-matrices-f

  setIdentityM(scaleMatrix, 0);
  setIdentityM(translateMatrix, 0);
  setIdentityM(rotateMatrix, 0);
public void translate(float x, float y, float z) {
    translateM(translateMatrix, 0, x, y, z);
    buildObjectModelMatrix();
}

public void rotate(float angle, float x, float y, float z) {
    rotateM(rotateMatrix, 0, angle, x, y, z);
    buildObjectModelMatrix();
}

public void scale(float x, float y,float z) {
    scaleM(scaleMatrix, 0, x, y, z);
    buildObjectModelMatrix();
}

private void buildObjectModelMatrix() {
    multiplyMM(tempM, 0, scaleMatrix, 0, rotateMatrix, 0);
    multiplyMM(objectMatrix, 0, tempM, 0, translateMatrix, 0);
}

РЕШЕНО: Проблемът в цялата работа е, че ако мащабирате преди да преведете, получавате разлика в разстоянието, което превеждате! правилният код за умножаване на вашите матрици трябва да бъде (поправете ме, ако греша)

    private void buildObjectModelMatrix() {
    multiplyMM(tempM, 0, translateMatrix, 0, rotateMatrix, 0);
    multiplyMM(objectMatrix, 0, tempM, 0, scaleMatrix, 0);
}

с това първо превеждате и завъртате. След това можете да мащабирате обекта.

Тествано с множество обекти... така че се надявам това да е помогнало :)


person LordSmith    schedule 29.09.2014    source източник


Отговори (1)


Знаете, че това е най-често срещаният проблем при повечето хора, когато започват да се занимават с матрични операции. Как работи умножението на матрицата е така, сякаш гледате от изгледа на обектите от първо лице и получавате някои команди: Например, ако сте започнали от (0,0,0) с лице към положителната ос X и up ще бъде положителна ос Y, тогава преводът (a,0,0) ще означава "върви напред", преведете (0,0,a) би означавало "завийте наляво", завъртане (a, 0, 1, 0) би означавало "завийте наляво"...

Така че, ако във вашия случай сте мащабирали с 3 единици, завъртяли сте с 90 градуса и след това сте превели с (2,0,0), това, което се случва, е, че първо се увеличавате с мащаб от 3, след което обръщате 90 градуса, така че сега сте изправени пред положителни Z, които все още са доста големи. След това отивате напред с 2 единици, измерени във вашата собствена координатна система, което означава, че всъщност ще отидете до (0,0,2*3). Така че завършвате при (0,0,6), гледайки към положителната ос Z.

Вярвам, че този начин е най-добрият, за да можете да си представите какво се случва, когато се занимавате с подобни операции. И може да ви спаси живота, когато имате грешка в реда на работа на матрицата.

Трябва да знаете, че въпреки че този вид работа с матрица е нормална, когато започвате с 3D сцена, трябва да опитате да преминете към по-добра система възможно най-скоро. Това, което най-често използвам, е да имам обектна структура/клас, който съдържа 3 вектора: position, forward и up (това е много като използването на glLookAt, но не е напълно същото). Така че, когато разполагате с тези 3 вектора, можете просто да зададете конкретна позиция или ротация, като използвате тригонометрия или вашите матрични инструменти, като умножите векторите с матрици вместо матриците с матрици. Или можете да работите с тях вътрешно (от първо лице), където например „давай напред“ ще бъде направено като position = position + position*forward*scale, завиване наляво ще означава завъртане на forward вектор около up вектор. Както и да е, надявам се да разбера как да манипулирате тези 3 вектора, за да получите желания ефект... И така, това, което трябва да направите, за да реконструирате матрицата от тези 3 вектора, е да генерирате друг вектор right, който е кръстосано произведение на up и forward след това матрицата на модела се състои от:

right.x,    right.y,    right.z, .0
up.x,       up.y,       up.z, .0
forward.x,  forward.y,  forward.z,  .0
position.x, position.y, position.z, 1.0

Само имайте предвид, че редът ред-колона може да се промени в зависимост от това, с което работите.

Надявам се това да ви даде по-добро разбиране...

person Matic Oblak    schedule 01.10.2014