У меня есть файл OBJ & MTL, экспортированный из 3DS Max, который является полным набором шахмат. В своем конечном результате я хотел бы иметь возможность выбрать игровой фрагмент, а затем выбрать квадрат, чтобы переместить его тоже. Элементы, с которыми у меня возникают проблемы при соединении:
У меня импортер объектов работает двумя способами.
1) Сгруппируйте все вместе с подобными материалами в структуру, называемую Mesh
, и переберите все model.meshes
, отрисовывая каждый кадр.
2) Определите игровое поле, каждый квадрат и каждый игровой элемент и поместите соответствующие вершины, материал и т. Д. В структуру под названием GroupObject
. Они помещены в model.objects
, который я перебираю, рисуя каждый кадр.
Вот скриншот того, как выглядит каждая опция, описанная в # 1 и # 2. В верхней половине SS я просто вытягиваю сетки, и все штриховки выглядят правильно, но ничего нельзя выбрать. В нижней половине я могу просто выбрать игровую фигуру или квадрат, но модель выглядит как дерьмо.
http://img815.imageshack.us/img815/2158/chesst.png
Кроме того, если я использую шейдер с кодом из # 2, панорамирование и масштабирование замедляются до сканирования. Это почти полностью не отвечает.
Вот метод, который вызывается для рисования объектов в каждом кадре. Первые 2 прокомментированные строки - это то, где я пробую вариант 1 и просто нарисую свою структуру Mesh
, и это выглядит хорошо Поворот и масштабирование также плавные, но я не могу выбрать объект, потому что я не могу сделать glPushName для Mesh
. В данный момент код настраивается циклически по каждому model.objects
, поэтому я могу запустить glPushName( (int)object );
, который необходим для выбора / выбора игрового элемента или квадрата. В закомментированном разделе я пытаюсь применить шейдер, который работает очень медленно при цикле по model.objects
(без замедления при цикле model.mesh
)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//for (int i = 0; i < model.getNumberOfMeshes(); ++i)
//{
for ( int i = 0; i < (int)model.objects.size(); i++ )
{
ModelOBJ::GroupObject *object = model.objects[i];
glPushName( (int)object );
int faceSize = (int)object->faces.size();
for ( int j = 0; j < faceSize; j++ )
{
ModelOBJ::Face *face = object->faces[j];
pMaterial = &model.getMaterial( face->materialId );
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (GLfloat *)pMaterial->ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (GLfloat *)pMaterial->diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat *)pMaterial->specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);
glDisable(GL_TEXTURE_2D);
drawFace( *face );
//if (pMaterial->bumpMapFilename.empty())
//{
// Per fragment Blinn-Phong code path.
// glUseProgram(blinnPhongShader);
// // Bind the color map texture.
// texture = nullTexture;
// if (enableTextures)
// {
// iter = modelTextures.find(pMaterial->colorMapFilename);
// if (iter != modelTextures.end())
// texture = iter->second;
// }
// glActiveTexture(GL_TEXTURE0);
// glEnable(GL_TEXTURE_2D);
// glBindTexture(GL_TEXTURE_2D, texture);
// // Update shader parameters.
// glUniform1i(glGetUniformLocation(
// blinnPhongShader, "colorMap"), 0);
// glUniform1f(glGetUniformLocation(
// blinnPhongShader, "materialAlpha"), pMaterial->alpha);
//}
}
glPopName();
}
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
glDisable(GL_BLEND);
Вот метод drawFace, если он уместен
void GLEngine::drawFace(ModelOBJ::Face &face)
{
if ( (int)face.numVertices <= 3 )
glBegin(GL_TRIANGLES);
else
glBegin(GL_POLYGON);
for ( int v = 0; v < (int)face.numVertices; v++ )
{
if ( (int)face.numUVWs > v && face.UVWs != NULL )
glTexCoord2f(face.UVWs[v]->x, face.UVWs[v]->y);
if ( (int)face.numNormals > v && face.normals != NULL )
glTexCoord3d(face.normals[v]->x, face.normals[v]->y, face.normals[v]->z);
if ( (int)face.numVertices > v && face.vertices != NULL )
glVertex3f(face.vertices[v]->x, face.vertices[v]->y, face.vertices[v]->z);
}
glEnd();
}
А вот шейдер, который я использую
Per-fragment Blinn-Phong shader for a single directional light source.
[vert]
varying vec3 normal;
void main()
{
normal = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
[frag]
uniform sampler2D colorMap;
uniform float materialAlpha;
varying vec3 normal;
void main()
{
vec3 n = normalize(normal);
float nDotL = max(0.0, dot(n, gl_LightSource[0].position.xyz));
float nDotH = max(0.0, dot(normal, vec3(gl_LightSource[0].halfVector)));
float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);
vec4 ambient = gl_FrontLightProduct[0].ambient;
vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL;
vec4 specular = gl_FrontLightProduct[0].specular * power;
vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;
gl_FragColor = color * texture2D(colorMap, gl_TexCoord[0].st);
gl_FragColor.a = materialAlpha;
}
Как бы вы объединили все эти функции вместе? Моя первая мысль - нарисовать все model.objects
без информации о материале и сделать их прозрачными. Затем пропустите второй цикл и нарисуйте все model.meshes
в комплекте с материалом и используя шейдер. Но потом я подумал, когда я начну перемещать игровые фигуры на новую клетку, как я буду следить за тем, чтобы к новой позиции фигуры применялась правильная заливка. Когда я выберу прозрачный GroupObject
и переведу его на новый квадрат, будет ли фигура иметь правильную штриховку?
Как лучше всего решить мою проблему?