i'm working on a project where i'm using OpenMesh to read stl and obj files and draw them on the screen using openGL. i've been doing the following,
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/IO/MeshIO.hh>
OpenMesh::TriMesh_ArrayKernelT<> mesh;
std::vector<point> vertices;
std::vector<point> normals;
void readMesh(std::string file)
{
OpenMesh::IO::read_mesh(mesh, file);
mesh.requestFaceNormals();
mesh.request_vertex_normals();
mesh.updateNormals();
vertices.clear();
normals.clear();
for (auto face : mesh.faces())
{
for (auto vertex : mesh.fv_range(face))
{
auto point = mesh.point(vertex);
auto normal = mesh.normal(face);
vertices.push_back(point);
normals.push_back(normal);
}
}
mesh.releaseFaceNormals();
mesh.releaseVertexNormals();
}
and when drawing i just pass the vertices
and normals
vectors to the vertex shader like this
void paint()
{
glSetAttributeArray(0, vertices.data());
glSetAttributeArray(1, normals.data());
glDrawArrays(GL_TRIANGLES, 0, vertices.length());
}
where the vertex shader looks like this:
attribute vec3 position;
attribute vec3 normal;
uniform mat4 modelViewMatrix;
void main(void)
{
vec4 color = vec4(0.25, 0.25, 0.25, 0.0);
vec4 P = vec4(position, 0);
vec4 N = vec4(normal, 0);
vec3 L = vec3(20, 20, 20) - position;
vec3 V = -position;
N = normalize(N);
L = normalize(L);
V = normalize(V);
vec3 R = reflect(-L, vec3(N));
vec3 diffuse = max(dot(vec3(N), L), 0.0) * color.rgb;
vec3 specular = pow(max(dot(R, V), 0.0), 0.2) * vec3(0.1, 0.1, 0.1);
color = vec4(color.a * (ambient + diffuse + specular), color.a);
color = clamp(color, 0.0, 1.0);
gl_Color = color;
gl_Position = modelViewMatrix * P;
}
and the fragment shader is:
void main(void)
{
gl_FragColor = gl_Color;
}
this produces pretty good results, but the idea of having another copy of the vertices and normals stored in another location (normals
and vertices
) to be able to draw the mesh looks very counter-intuitive.
i was wondering if i can use openGL buffers with openMesh to optimize this. i've been searching for anything concerning this topic for a while but found nothing.
See Vertex Specification. You can create 2 Vertex Buffer Object for the verticex cooridantes and nortmal vertors:
If you use OpenGL 3.0 or later, then you can specify a Vertex Array Object a nd state the vertex specification:
When you want to draw the mesh, then it is sufficient to bind the VAO:
If you use OpenGL 2.0, the you cannot create a VAO, thus you have to specify the arrays of generic vertex attribute data, before drawing the mesh:
Furthermore note, that the attribute indices are not guaranteed to be 0 and 1. The attribute indices can be any arbitrary number.
If you would use GLSL version 3.30 the it would be possible to set the attribute indices in the shader code by Layout Qualifier.
Anyway you an define the attribute indices by
glBindAttribLocation
before linking the program or retrieve the attribute indices byglGetAttribLocation
after linking the program.