Проблема с рендерингом меша из файла OBJ

У меня проблема с адаптацией и / или я предполагаю, что понимаю вершины / индексы / грани в файле OBJ. Я хочу в конечном итоге проанализировать файл OBJ программно, но сначала мне нужно понять, как это сделать вручную. Для этого я использую адаптацию примера из GLWallpaperService (предоставленного разработчиком в Интернете).

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

public class GLCube {
private final int _nrOfVertices = 8;

private FloatBuffer _vertexBuffer;
private FloatBuffer _normalBuffer;
private ShortBuffer _indiceBuffer;

public GLCube() {
    this.init();
}

private void init() {
    // 3 is the number of coordinates to each vertex.
    _vertexBuffer = BufferFactory.createFloatBuffer(_nrOfVertices * 3);
    _normalBuffer = BufferFactory.createFloatBuffer(18);
    _indiceBuffer = BufferFactory.createShortBuffer(72);

    // Coordinates for the vertexes of the cube.
    float[] vertexCoords = {
            /*
            1f,  1f,  0f,
            0f,  1f,  0f, 
            0f,  0f,  0f, 
            1f,  0f,  0f, 
            1f,  0f, -1f, 
            1f,  1f, -1f, 
            0f,  1f, -1f, 
            0f,  0f, -1f,
            */
            2.195671f, -0.176713f, -1.292541f,
            2.195671f, -0.176713f,  0.707459f,
            0.195671f, -0.176713f,  0.707459f,
            0.195672f, -0.176713f, -1.292542f,
            2.195672f,  1.823287f, -1.292541f,
            2.195671f,  1.823287f,  0.707460f,
            0.195671f,  1.823287f,  0.707459f,
            0.195671f,  1.823287f, -1.292541f
    };

    short[] indicesArray = {/*
            0, 1, 2,   0, 2, 3,
            3, 4, 0,   4, 5, 0,
            7, 2, 6,   6, 2, 1,
            4, 7, 5,   7, 6, 5,
            1, 0, 6,   6, 0, 5,
            2, 7, 3,   7, 4, 3
            */
            1,1,2, 1,3,1,
            1,1,3, 1,4,1,
            5,2,8, 2,7,2,
            5,2,7, 2,6,2,
            1,3,5, 3,6,3,
            1,3,6, 3,2,3,
            2,4,6, 4,7,4,
            2,4,7, 4,3,4,
            3,5,7, 5,8,5,
            3,5,8, 5,4,5,
            5,6,1, 6,4,6,
            5,6,4, 6,8,6
            };

    //Coordinates for Normal Vector. Used for Lighting calculations
    float[] normalCoords = {/*
             0f, 0f, 1f,   0f, 0f, 1f,   
             0f, 0f, 1f,   0f, 0f, 1f,   
             0f, 0f, 1f,   0f, 0f, 1f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
            -1f, 0f, 0f,  -1f, 0f, 0f,  
            -1f, 0f, 0f,  -1f, 0f, 0f,  
            -1f, 0f, 0f,  -1f, 0f, 0f,  
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 1f, 0f,   0f, 1f, 0f,   
             0f, 1f, 0f,   0f, 1f, 0f,   
             0f, 1f, 0f,   0f, 1f, 0f,  
             0f,-1f, 0f,   0f,-1f, 0f,   
             0f,-1f, 0f,   0f,-1f, 0f,   
             0f,-1f, 0f,   0f,-1f, 0f   
             */
             0f, -1f,  0f,
             0f,  1f,  0f,
             1f, -0f,  0f,
            -0f, -0f,  1f,
            -1f, -0f, -0f,
             0f,  0f, -1f
    };

    _vertexBuffer.put(vertexCoords);
    _normalBuffer.put(normalCoords);
    _indiceBuffer.put(indicesArray);

    _indiceBuffer.position(0);
    _vertexBuffer.position(0);
    _normalBuffer.position(0);

}

public void draw(GL10 gl) {
    // 3 coordinates in each vertex
    // 0 is the space between each vertex. They are densely packed in the array, so the value is 0
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

    // 0 is the space between each vertex. They are densely packed in the array, so the value is 0
    gl.glNormalPointer(GL10.GL_FLOAT, 0, _normalBuffer);

    gl.glColor4f(1.0f, 0f, 0f, 1f);     //Red
    gl.glDrawElements(GL10.GL_TRIANGLES, 72, GL10.GL_UNSIGNED_SHORT, _indiceBuffer);
}
}

Это файл Obj, и, возможно, я просто не помещаю значения в правильные массивы, но я какое-то время пытался понять это и, честно говоря, просто не имею никакого опыта работы с OpenGL, так что это мой первый проект, пытающийся работать с этим.

# Blender v2.58 (sub 1) OBJ File: ''
# www.blender.org
v 2.195671 -0.176713 -1.292541
v 2.195671 -0.176713 0.707459
v 0.195671 -0.176713 0.707459
v 0.195672 -0.176713 -1.292542
v 2.195672 1.823287 -1.292541
v 2.195671 1.823287 0.707460
v 0.195671 1.823287 0.707459
v 0.195671 1.823287 -1.292541
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 -0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl (null)
s off
f 1//1 2//1 3//1
f 1//1 3//1 4//1
f 5//2 8//2 7//2
f 5//2 7//2 6//2
f 1//3 5//3 6//3
f 1//3 6//3 2//3
f 2//4 6//4 7//4
f 2//4 7//4 3//4
f 3//5 7//5 8//5
f 3//5 8//5 4//5
f 5//6 1//6 4//6
f 5//6 4//6 8//6

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

Ответ, содержащий, что изменить, был бы потрясающим. знак равно


person Joey    schedule 01.08.2011    source источник


Ответы (1)


Я думаю, вы неправильно интерпретируете формат .obj. Ознакомьтесь с этим документом.

По сути, индексы для ваших лиц в vertexCoords должны быть первыми целыми числами. Каждое лицо определяется индексами в таком формате:

f v1/t1/n1 v2/t2/n2 v3/t3/n3

Где v - это индексы вершин, t - индексы координат текстуры, а n - нормальные индексы.

Итак, для этой линии (которая определяет одну грань / треугольник)

f 1//1 2//1 3//1

индексы вершин будут 1,2,3, а нормальные индексы 1,1,1. У вас нет координат текстуры, поэтому нет индексов и, следовательно, двойной косой черты.

Имейте в виду, что индексы вершин, составляющих грань, и индексы связанных нормалей различны. Итак, вам нужно будет создать два набора индексов. (См. Мою правку ниже о glDrawElements)

Еще одна небольшая деталь - это помнить, что файлы .obj начинают отсчет с индексов с 1, хотя это может быть (а возможно, и есть) 0-е значение в вашем массиве. Поэтому вам придется это учитывать (т.е. вычесть 1 из всех значений индекса).

Изменить. Глядя на ваш код, я вижу, что вы используете glDrawElements. Насколько я знаю (но поправьте меня, если я ошибаюсь), это не позволяет вам иметь несколько (разных) наборов индексов для вершин, текскордов и нормалей. Таким образом, вам придется изменить ваши обычные данные, чтобы они соответствовали тем же индексам, что и для ваших вершин.

person Bart    schedule 01.08.2011
comment
хорошо, я исследовал ссылку, и из того, что вы сказали, я думаю, что я ее понял, но я все еще не конвертирую должным образом, лол ... в любом случае вы могли бы изменить мой код в ответ с данными, которые я предоставил, чтобы показать мне, что вы имеете в виду? Если вы исправите мой код, я гарантирую, что ответят - =) - person Joey; 02.08.2011
comment
Забудьте пока о нормалях. Только те вершины, которые вы указали. С учетом .obj массив индексов должен выглядеть так: pastebin.com/Sj4sigPq У меня нет означает компилировать / запускать / проверять ваш код, но, по крайней мере, так должны выглядеть индексы. Это то, что вы пробовали? - person Bart; 02.08.2011
comment
хорошо, это имеет смысл! Я не вычитал 1 из каждого индекса. это дает мне немного больше понимания конверсий. Ответ принят. Любое дополнительное объяснение было бы замечательно, но вы превзошли мои ожидания - = D - person Joey; 02.08.2011
comment
на самом деле в примере, который я использую из GLWallpaperService, было несколько элементов glDrawElements с отдельными сторонами для каждого из них. Есть ли лучший способ сделать это без отдельного набора индексов для каждой формы? - person Joey; 02.08.2011
comment
Ах, теперь я понял. Он рисует куб с 6 сторонами сплошного цвета. В этом конкретном случае дублирование вершин необходимо, поскольку все атрибуты указываются на уровне вершин. Конечно, если у вас есть сетка с одним наложением цвета / материала или текстуры, вам не нужно этого делать. - person Bart; 05.08.2011