OpenGL ES20 — Wavefront —> glDrawElements —> не пирамида, а странная форма?

РЕДАКТИРОВАТЬ 2:

Решение: ошибка копирования и вставки: буфер цвета отправлен как буфер положения.


Разбираем мой .obj (волновой фронт), который представляет собой пирамиду, триангулируем там, где это необходимо, и передаем все это в буферы. Буферы выглядят следующим образом:

Буфер вершин:

private FloatBuffer mPositionBuffer = null;
// from looping through buffer + print:
#0 = -0.5, 0.0, -0.5
#3 = 0.5, 0.0, -0.5
#6 = 0.5, 0.0, 0.5
#9 = -0.5, 0.0, 0.5
#12 = 0.5, 0.0, 0.5
#15 = 0.5, 0.0, -0.5
#18 = 0.0, 1.0, 0.0
#21 = 0.5, 0.0, -0.5
#24 = -0.5, 0.0, -0.5
#27 = 0.0, 1.0, 0.0
#30 = -0.5, 0.0, -0.5
#33 = -0.5, 0.0, 0.5
#36 = 0.0, 1.0, 0.0
#39 = -0.5, 0.0, 0.5
#42 = 0.5, 0.0, 0.5
#45 = 0.0, 1.0, 0.0

Буфер цвета:

private ByteBuffer mColorBuffer = null;
#0 = 1, 1, 1, 1
#4 = 1, 1, 1, 1
#8 = 1, 1, 1, 1
#12 = 1, 1, 1, 1
#16 = 1, 1, 1, 1
#20 = 1, 1, 1, 1
#24 = 1, 1, 1, 1
#28 = 1, 1, 1, 1
#32 = 1, 1, 1, 1
#36 = 1, 1, 1, 1
#40 = 1, 1, 1, 1
#44 = 1, 1, 1, 1
#48 = 1, 1, 1, 1
#52 = 1, 1, 1, 1
#56 = 1, 1, 1, 1
#60 = 1, 1, 1, 1

Обычный буфер:

private FloatBuffer mNormalBuffer = null;



#0 = 0.0, 0.0, 0.0
#3 = 1.0, 0.0, 0.0
#6 = 1.0, 1.0, 0.0
#9 = 0.0, 1.0, 0.0
#12 = 0.0, 0.0, 0.0
#15 = 1.0, 0.0, 0.0
#18 = 0.5, 1.0, 0.0
#21 = 0.0, 0.0, 0.0
#24 = 1.0, 0.0, 0.0
#27 = 0.5, 1.0, 0.0
#30 = 0.0, 0.0, 0.0
#33 = 1.0, 0.0, 0.0
#36 = 0.5, 1.0, 0.0
#39 = 0.0, 0.0, 0.0
#42 = 1.0, 0.0, 0.0
#45 = 0.5, 1.0, 0.0

Буфер индексов:

private ShortBuffer mIndexBuffer = null;
#0 = 0, 1, 3
#3 = 1, 2, 3
#6 = 4, 5, 6
#9 = 7, 8, 9
#12 = 10, 11, 12
#15 = 13, 14, 15

При объединении вершин + граней в моем сознании получается пирамида, как и должно быть. Простая модель. Я рисую это следующим образом:

// data above are put in these buffers





    mColorBuffer.position(0);
    mNormalBuffer.position(0);
    mIndexBuffer.position(0);
    mPositionBuffer.position(0);

    GLES20.glVertexAttribPointer(mShader.getGLLocation(BaseShader.A_POSITION), 3, GLES20.GL_FLOAT, false,
            0, mColorBuffer);

    GLES20.glEnableVertexAttribArray(mShader.getGLLocation(BaseShader.A_POSITION));

    GLES20.glVertexAttribPointer(mShader.getGLLocation(BaseShader.A_COLOR), 4, GLES20.GL_BYTE, false,
                0, mColorBuffer);

    GLES20.glEnableVertexAttribArray(mShader.getGLLocation(BaseShader.A_COLOR));

    GLES20.glVertexAttribPointer(mShader.getGLLocation(BaseShader.A_NORMAL), 3, GLES20.GL_FLOAT, false,
                0, mNormalBuffer);

    GLES20.glEnableVertexAttribArray(mShader.getGLLocation(BaseShader.A_NORMAL));

    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
    GLES20.glUniformMatrix4fv(mShader.getGLLocation(BaseShader.U_MVPMATRIX), 1, false, mMVPMatrix, 0);
    GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, mIndexBuffer.capacity(), GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);

Но есть объект, который не очень похож на пирамиду и в результате "шатается", т.е. если я его перевожу (без поворота, но код выглядит так (и выполняется до отрисовки):

    Matrix.translateM(mModelMatrix, 0, mTranslation[0], mTranslation[1], mTranslation[2]);
    Matrix.scaleM(mModelMatrix, 0, mScale[0], mScale[1], mScale[1]);

    Matrix.rotateM(mModelMatrix, 0, mRotation[0], 0, 1, 0);
    Matrix.rotateM(mModelMatrix, 0, mRotation[1], 1, 0, 0);
    Matrix.rotateM(mModelMatrix, 0, mRotation[2], 0, 0, 1);
    Matrix.multiplyMM(mMVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

Мне кажется, что индексы передаются неправильно? К сожалению, рисуется только одна сторона пирамиды.

Должен ли я использовать другие значения для функции glDrawElements? Если нужно, могу выложить скриншот или скрин анимации перевода. Большое спасибо за любую помощь!

РЕДАКТИРОВАТЬ:

В случае, если это как-то связано с этим:

Я звоню этим:

    GLES20.glClearColor(0, 0, 0, 1);
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    GLES20.glDepthFunc(GLES20.GL_LEQUAL);

person damian    schedule 13.03.2014    source источник


Ответы (1)


Я не совсем уверен, но это похоже на проблему отбраковки (вы когда-нибудь устанавливали отбраковку? Я не знаю, какое значение по умолчанию). ... Также вы уверены, что GL_TRIANGLE_FAN - это то, как устроены ваши индексы? больше похоже на расположение GL_TRIANGLE_STRIP.

РЕДАКТИРОВАТЬ: Теперь, когда я смотрю на ваши вершины, я думаю, что GL_TRIANGLES — это то, что вам нужно использовать, поэтому я ошибся в первый раз. Простите за это.

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

(0,0,0, // point0
,1,0,0, // point1
,0,1,0, // point2
,0,0,1) // point3

так что это даст нам массив из 12 длин с 4 наборами координат, теперь вот как будут выглядеть наши индексы, если мы используем GL_TRIANGLE_STRIP:

(0,1,2,3,0,1) 

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

и если мы используем GL_TRIANGLES, то же самое будет выглядеть так:

(0,1,2,
2,1,3,
3,1,0,
0,2,3)

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

В вашем случае кажется, что у вас есть повторяющиеся вершины, поэтому стены могут иметь правильные нормали и выглядеть плоскими. Таким образом, у вас есть отдельные вершины для каждой стены, даже если они совпадают со следующей. Опять же, мой совет: оставьте только один треугольник — три вершины, три индекса и добавляйте еще один за другим, пока не получите полную фигуру.

person kalinrj    schedule 13.03.2014
comment
Привет, теперь, когда вы упомянули об этом, я (наконец-то) прочитал разницу между веером и полосой, и вы правы, пирамида (с полом), вероятно, не может отображаться как веер. Но я не думаю, что это вся проблема. Я пробовал отбраковывать, но я не уверен, какой именно вариант является правильным, у вас есть предложение? - person damian; 13.03.2014
comment
если смотреть на вершины стены 1,2 и 3 (в таком порядке) против часовой стрелки, это GL_FRONT, иначе это GL_BACK. Чтобы включить отбраковку, вызовите: 'glEnable(GL_CULL_FACE); glCullFace(GL_FRONT);' - person kalinrj; 13.03.2014
comment
.. эээ, на самом деле это неправильно, вы можете указать направление CW или CCW. Здесь я нашел полезную статью, которая включает подробное объяснение констант отбраковки ссылка - person kalinrj; 13.03.2014
comment
Итак, я изменил его на TRIANGLE_STRIP, но реального улучшения не произошло.. также включил GL_CULL_FACE, но это тоже не помогло. пирамида, но без одной стороны. Я полагаю, это потому, что я не могу добавлять индексы в glDrawArrays? Есть ли способ, как я могу исправить/обойти это? - person damian; 14.03.2014
comment
Я не фанат glDrawArrays, хорошо иметь контроль над вашими индексами. Если бы я был на вашем месте, я бы начал с рисования одного треугольника и продолжал добавлять его, пока не получил полную пирамиду. Так или иначе работает TRIANGLE_STRIP. В противном случае вы можете просто использовать GL_TRIANGLES (намного проще для понимания). PS. почему у тебя так много вершин? ты сам пришел с ними? - person kalinrj; 14.03.2014
comment
Хорошо, моя ошибка заключалась в том, что я отправил цветовой буфер в качестве буфера положения. Ошибка копипасты... мне понадобилось пару дней, чтобы увидеть это. В любом случае спасибо! - person damian; 14.03.2014