2012-06-27 3 views
4

Я писал загрузчик .obj для openGl. Геометрия загружается отлично, но нормали всегда перепутаны. Я пытался экспортировать модели в 2 разных программах, и ничего не работает. Насколько я знаю, это то, как вы положили в нормальный к GL_TRIANGLESНормали, действующие странно в openGL

 glNormal3fv(norm1); 
    glVertex3fv(vert1); 
    glNormal3fv(norm2); 
    glVertex3fv(vert2); 
    glNormal3fv(norm3); 
    glVertex3fv(vert3); 

(нормали ссылки на GLfloats в остальной части кода.)

EDIT: Вот картина isohedron с разбитыми нормалей enter image description here

Это полный OBJ код загрузчика и файла:

void loadOBJFromFile(NSString *path,float movex,float movey) 
{ 
    NSString *contentns = [[NSString alloc]initWithContentsOfFile:path encoding:NSASCIIStringEncoding error:NULL]; 
    NSArray *pieces = [contentns componentsSeparatedByString:@"#"]; 
    //creating the arrays to read the vertecies and normals from. 
    NSArray *normals = [[pieces objectAtIndex:3]componentsSeparatedByString:@"\n"]; 
    NSArray *vertecies = [[pieces objectAtIndex:2]componentsSeparatedByString:@"\n"]; 
    //The +1 is to make sure we ignore the texture/ material definition that vomes before the faces. 
    int normalCount = [[normals objectAtIndex:0]intValue]+2; 
    int faceCount = [[normals objectAtIndex:normalCount]intValue]; 
    //glTranslatef(movex, 0, movey); 

glBegin(GL_TRIANGLES); 
{ 
for (int i = 0; i < faceCount;i++) 
{ 
    //aquires all the numbers in thye current face. 
    NSArray *currentFace = [[normals objectAtIndex:normalCount+i+1]componentsSeparatedByString:@" "]; 
    NSArray *v1 = [[currentFace objectAtIndex:1]componentsSeparatedByString:@"//"]; 
    NSArray *v2 = [[currentFace objectAtIndex:2]componentsSeparatedByString:@"//"]; 
    NSArray *v3 = [[currentFace objectAtIndex:3]componentsSeparatedByString:@"//"]; 

    //crewatres the arrays to contain the vertecies 
    NSArray *vertex1 = [[vertecies objectAtIndex:[[v1 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "]; 
    NSArray *vertex2 = [[vertecies objectAtIndex:[[v2 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "]; 
    NSArray *vertex3 = [[vertecies objectAtIndex:[[v3 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "]; 
    //creates all the arrays for the normals 
    NSArray *normal1 = [[normals objectAtIndex:[[v1 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "]; 
    NSArray *normal2 = [[normals objectAtIndex:[[v2 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "]; 
    NSArray *normal3 = [[normals objectAtIndex:[[v3 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "]; 

    //creates the vertecies coordinates 
    GLfloat vert1[] = {[[vertex1 objectAtIndex:1]floatValue],[[vertex1 objectAtIndex:2]floatValue],[[vertex1 objectAtIndex:3]floatValue]}; 
    GLfloat vert2[] = {[[vertex2 objectAtIndex:1]floatValue],[[vertex2 objectAtIndex:2]floatValue],[[vertex2 objectAtIndex:3]floatValue]}; 
    GLfloat vert3[] = {[[vertex3 objectAtIndex:1]floatValue],[[vertex3 objectAtIndex:2]floatValue],[[vertex3 objectAtIndex:3]floatValue]}; 
    //creates the normals coordinates 

    GLfloat norm1[] = {[[normal1 objectAtIndex:1]floatValue],[[normal1 objectAtIndex:2]floatValue],[[normal1 objectAtIndex:3]floatValue]}; 
    GLfloat norm2[] = {[[normal2 objectAtIndex:1]floatValue],[[normal2 objectAtIndex:2]floatValue],[[normal2 objectAtIndex:3]floatValue]}; 
    GLfloat norm3[] = {[[normal3 objectAtIndex:1]floatValue],[[normal3 objectAtIndex:2]floatValue],[[normal3 objectAtIndex:3]floatValue]}; 

    glNormal3fv(norm1); 
    glVertex3fv(vert1); 
    glNormal3fv(norm2); 
    glVertex3fv(vert2); 
    glNormal3fv(norm3); 
    glVertex3fv(vert3); 
}} 
glEnd(); 

}

OBJ файл:

#Wavefront OBJ file created by Hexagon 2 
mtllib object.mtl 
g Form0 
usemtl def_surf_mat 
# 12 
v -12.533 4.78719 0 
v -12.533 20.2788 0 
v -7.74583 12.533 -12.533 
v -7.74583 12.533 12.533 
v 0 0 -7.74583 
v 0 0 7.74583 
v 0 25.066 -7.74583 
v 0 25.066 7.74583 
v 7.74583 12.533 -12.533 
v 7.74583 12.533 12.533 
v 12.533 4.78719 0 
v 12.533 20.2788 0 
# 12 
vn -0.850651 -0.525731 0 
vn -0.850651 0.525731 1.50014e-08 
vn -0.525731 -1.50014e-08 -0.850651 
vn -0.525731 0 0.850651 
vn 1.50014e-08 -0.850651 -0.525731 
vn -1.50014e-08 -0.850651 0.525731 
vn -1.50014e-08 0.850651 -0.525731 
vn 1.50014e-08 0.850651 0.525731 
vn 0.525731 0 -0.850651 
vn 0.525731 7.5007e-09 0.850651 
vn 0.850651 -0.525731 1.50014e-08 
vn 0.850651 0.525731 -1.50014e-08 
usemtl def_surf_mat 
20 
f 7//7 8//8 12//12 
f 7//7 2//2 8//8 
f 8//8 4//4 10//10 
f 6//6 10//10 4//4 
f 7//7 9//9 3//3 
f 5//5 3//3 9//9 
f 6//6 5//5 11//11 
f 6//6 1//1 5//5 
f 1//1 4//4 2//2 
f 1//1 2//2 3//3 
f 12//12 11//11 9//9 
f 12//12 10//10 11//11 
f 2//2 4//4 8//8 
f 10//10 12//12 8//8 
f 12//12 9//9 7//7 
f 3//3 2//2 7//7 
f 3//3 5//5 1//1 
f 4//4 1//1 6//6 
f 9//9 11//11 5//5 
f 11//11 10//10 6//6 
+0

Как вы загружаете эти нормали? Отладили ли вы его, чтобы убедиться, что они уже загружены правильно? –

+0

Также проверьте, являются ли ваши нормали единичной длиной. .OBJ не гарантирует этого. –

+3

в качестве побочного примечания, попробуйте избегать непосредственного режима в будущем, он очень старый и удален в новых версиях API opengl, загляните в объекты буфера Vertex и glew –

ответ

0

Ответ очень прост. Объект загружался правильно из объектного файла. Кодер загрузчика может быть оптимизирован намного больше. После вызова

glEnable (GL_CULL_FACE | GL_CULL_FACE_MODE);

EDIT Не могу поверить, что тогда я совершил такую ​​новичковую ошибку. Убирающее лицо помогло, но только немного. Реальная проблема заключалась в том, что я забыл очистить буфер глубины.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

Это должно решить проблему, если кто-либо еще испытывает одни и те же вещи.

Некоторая проблема была исправлена, мне на самом деле нужно было очистить другой буфер или поп матрицу или что-то в этом роде. Теперь геометрия освещения загружается точно так, как она появляется в редакторах и программах моделирования. Спасибо за вашу помощь.

1

С дополнительной информацией вы добавили к этому вопросу, я бегу из идей. Я также не могу прочитать Objective-C, но я бы предложил дважды проверить все индексирование массива и подсчет строки (возможно, распечатать все, чтобы увидеть, действительно ли это то, что вы ожидаете), поскольку синтаксический анализ основывается на доверии к точной компоновке и комментированию один экспортер создает внешний вид очень волосатый.

Оригинальный ответ:

Не видя вашего загрузчика кода или файл .obj, вот несколько вещей, чтобы проверить:

  • Как испортили? Совершенно неправильно, или просто, например. плоский затененный вместо гладкого затенения?
  • Являются ли эти нормы1, norm2 и т. Д. Массивами трех GLfloats?
  • В нормальных массивах содержатся нормальные значения (поэтому чтение их из файла работает)?
  • Ваши нормали нормализованы до длины 1?
  • Правильно ли проиндексированы нормали, т. Е. У вас есть правильная нормальная правильная вершина?
+0

Нормали совершенно неправильны. норма1 .... являются GLfloats. Нормали - это нормальные значения. Я не знаю, что вы гривой нормализованным. И нормали индексируются в правые вершины. – BlueSpud

+0

@BlueSpud Normalized означает, что они являются единицей длины, недействительной их величины и просто сохраняя направление. –

+0

Спасибо за разъяснение. Я меняю модель на единицу длины, но это не помогло. В любом случае спасибо. – BlueSpud

1

tl; dr но --- проверьте правильность знака ваших нормалей. В расчетах легко иметь нормали, указывающие в противоположном направлении, чем вы планировали. Например. они идут по правильной линии, но указывают внутри, а не снаружи. Ваше изображение соответствует этому виду или ошибке.

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

+0

Предполагая, что все ваши лица правильно раны :) – genpfault

+0

Я не на самом деле вычисляю нормали, я предположил, что то, что было в файле obj, уже было рассчитано. Это? потому что тогда это определенно проблема. – BlueSpud

+0

Я не знаком с этим файловым форматом. Но наличие элементов «vn» указывает мне, что нормали находятся в файле. Но эти нормали относятся к определенному типу «обмотки» треугольника. Они будут работать правильно, только если вы их визуализируете, передавая вершины в рендеринг в правильном порядке. –

1

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

Визуальные артефакты на вашем изображении выглядят как неправильная проверка глубины. (рисую только половину треугольника) Я предполагаю, что вы используете подкласс NSOpenGLView в IB (Interface Builder). Убедитесь, что вы используете буфер глубины из NSOpenGLView в IB Attribute Inspector (по умолчанию это нет). Общее значение буфера глубины - 24 бит, плюс 8 бит для буфера Stencil.


И вот некоторые предложения по улучшению вашей программы;

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

  • Используйте NSMutableArray для вершин, нормалей и граней.

  • Ваш OBJ-загрузчик не лучший способ разобрать OBJ-файл, поскольку он зависит от строки комментария (начиная с #). Я бы сделал:

    1. Прочитайте строки за строкой и сохраните их в виде массива строк.
    2. Прокрутите каждую строку и проверьте следующее:
    3. Если оно начинается с #, то пропустите, чтобы проанализировать линию.
    4. Если оно начинается с «v», добавьте следующие 3 числа в одну строку к массиву вершин.
    5. Если он начинается с «vn», добавьте следующие 3 числа в строку к нормальному массиву.
    6. Если оно начинается с «f», добавьте 3 лицевых индекса в массив лиц.
+0

На самом деле, я использую инструмент командной строки Foundation. У меня включен GL_DEPTH_TEST, но не GL_DEPTh. Даже после включения он по-прежнему выглядит странно. Я могу попытаться поместить приложение в конструктор интерфейса, потому что я намерен позже в любом случае. – BlueSpud

+1

@BlueSpud, да, пожалуйста, убедитесь, что у вас есть буфер глубины при создании контекста рендеринга OpenGL. Использование GLUT, ** glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) **. Затем очистите буфер глубины так же, как и чертеж каждого кадра: ** glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) **; – song

+0

Собственно, это разбило клиента. Я понятия не имею, почему, но я нашел свое решение. Благодарим вас за помощь, подтвердив мои подозрения в проблеме рендеринга и за способ оптимизации кода, потому что мне нужно сделать это значительно после загрузки примерно в 1000 полигонов. – BlueSpud