OpenGL загрузка OBJ модели, искажение текстуры - PullRequest
1 голос
/ 19 ноября 2011

Я решил импортировать формат Wavefront .OBJ в тестовую сцену, над которой я работаю.Я получаю модель (вершины), чтобы быть в нужном месте, и она отображается нормально.Когда я тогда применяю текстуру, многие вещи выглядят искаженными.Я проверил свою сцену Maya (там она выглядит хорошо), и объект имеет гораздо больше uv-координат, чем положений вершин (это то, что делает сцену странной в OpenGL, это мое предположение).

Как бы яидти о загрузке сцены, как это.Нужно ли дублировать вершины и как сохранить их в объекте буфера вершин?

1 Ответ

1 голос
/ 19 ноября 2011

Вы правы, что вам нужно дублировать вершины.В дополнение к этому вы должны отсортировать их в порядке отрисовки, то есть вы должны упорядочить вершины с теми же смещениями, что и у текстурных координат и нормалей.в основном вам понадобится такая структура:

float *verts = {v1_x,v1_y,v1_z,v1_w,v2_x,v2_y,v2_z,v2_w,...};
float *normals = {n1_x,n1_y,n1_z,n2_x,n2_y,n2_z,...};
float *texcoords = {t1_u,t1_v,t1_w,t2_u,t2_v,t2_w,...};

Однако это будет означать, что у вас есть по крайней мере 108 байт на треугольник.

 3(vert,norm,tex)
*3(xyz/uvw)
*3(points in tri)
*4(bytes in a float)) 
-----------------------
= 108

Вы можете значительно уменьшить это число, только дублируя вершины, которые на самом деле являются дубликатами (имеют одинаковую координату текстуры, вершины и нормали, что означает: сглаженные нормали и отсутствие границ UV) и используя объект Index Buffer для установкипорядок отрисовки.

Недавно я столкнулся с той же проблемой в небольшом проекте, и я просто разделил модели по жестким краям и границам UV-оболочки, создавая только необходимые дубликаты вершин.Затем я использовал glm.h и glm.cpp из Nate Robins и скопировал / отсортировал нормали и координаты текстуры в том же порядке, что и вершины.

Затем настройте VBO и IBO:

//this is for Data that does not change dynamically
//GL_DYNAMIC_DRAW and others are available
GLuint mDrawMode = GL_STATIC_DRAW;

//////////////////////////////////////////////////////////
//Setup the VBO
//////////////////////////////////////////////////////////
  GLuint mId;
  glGenBuffers(1, &mId);
  glBindBuffer(GL_ARRAY_BUFFER, mId);
  glBufferData(GL_ARRAY_BUFFER,
               mMaxNumberOfVertices * (mVertexBlockSize + mNormalBlockSize + mColorBlockSize + mTexCoordBlockSize),
               0,
               mDrawMode);
  glBufferSubData(GL_ARRAY_BUFFER, mVertexOffset, numberOfVertsToStore * mVertexBlockSize, vertices);
  glBufferSubData(GL_ARRAY_BUFFER, mNormalOffset, numberOfVertsToStore * mNormalBlockSize, normals);
  glBufferSubData(GL_ARRAY_BUFFER, mColorOffset, numberOfVertsToStore * mColorBlockSize, colors);
  glBufferSubData(GL_ARRAY_BUFFER, mTexCoordOffset, numberOfVertsToStore * mTexCoordBlockSize, texCoords);

//////////////////////////////////////////////////////////
//Setup the IBO
//////////////////////////////////////////////////////////
  GLuint IBOId;
  glGenBuffers(1, &IBOId);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOId);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, mMaxNumberOfIndices * sizeof(GLuint), 0, mDrawMode);
  glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numberOfIndicesToStore * sizeof(GLuint), indices);

//////////////////////////////////////////////////////////
//This is how to draw the object  
//////////////////////////////////////////////////////////
  glBindBuffer(GL_ARRAY_BUFFER, mId);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOId);

  //Enables and Disables are only necessary each draw
  //when they change between objects
  glEnableClientState(GL_VERTEX_ARRAY);
  glVertexPointer(mVertexComponents, GL_FLOAT, 0, (void*)mVertexOffset);
  if(mNormalBlockSize){
    glEnableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, 0, (void*)mNormalOffset);
  }
  if(mColorBlockSize){
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(mColorComponents, GL_FLOAT, 0, (void*)mColorOffset);
  }
  if(mTexCoordBlockSize){
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(mTexCoordComponents, GL_FLOAT, 0, (void*)mTexCoordOffset);
  }

  glDrawRangeElements(primMode,
                      idFirstVertex,
                      idLastVertex,
                      idLastVertex - idFirstVertex + 1,
                      mAttachedIndexBuffer->getDataType(),
                      0);

  if(mTexCoordBlockSize)
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  if(mColorBlockSize)
    glDisableClientState(GL_COLOR_ARRAY);
  if(mNormalBlockSize)
    glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_VERTEX_ARRAY);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...