0

I use OpenGL + OpenMesh to render a 3d mesh

My mesh reading and processing code:

void read(MyMesh &model, const string &path) {
    model.request_vertex_colors();
    model.request_face_normals();
    OpenMesh::IO::Options opt;
    opt += OpenMesh::IO::Options::VertexColor;
    opt += OpenMesh::IO::Options::FaceNormals;
    if (!OpenMesh::IO::read_mesh(model, path, opt)) {
        cerr << "read error\n";
        exit(1);
    }

    // fill the vertices and normals array
    for (auto f : model.faces())
        for (auto v : model.fv_range(f)){ // how can I get vertex texcoords based on face?
            vertices.push_back(model.point(v));
            normals.push_back(model.normal(f));
            colors.push_back(model.color(v));
        }
    model.release_vertex_colors();
    model.release_face_normals();
}

But I find that I can't get vertex texcoords based on the face in OpenMesh. It seems there isn't a function called model.texcoords(face_handle, vertex_handle) to let me get the vertex texcoords on this face.

Or can I get the texcoords index of each face like these in obj file:

f 481/1/1 480/2/1 24/3/1 25/4/1
f 477/5/2 7/6/2 17/7/2 18/8/2
f 1/9/3 326/10/3 11/11/3
f 482/12/4 481/1/4 25/4/4
f 478/13/5 477/5/5 18/8/5 19/14/5
f 2/15/6 1/9/6 11/11/6 12/16/6
f 479/17/7 478/13/7 19/14/7 20/18/7
f 3/19/8 2/15/8 12/16/8 13/20/8
f 8/21/9 479/17/9 20/18/9 21/22/9

I use glDrawArrays(...) to draw mesh.

Declarations

vector<MyMesh::Point> vertices; // `MyMesh::Point` is like float3 struct which has 3 float numbers in it  
vector<MyMesh::Point> normals;
vector<MyMesh::Point> colors;

unsigned int model_vbo[3], model_vao;

Data bind

glGenBuffers(3, model_vbo);
glGenVertexArrays(1, &model_vao);

glBindBuffer(GL_ARRAY_BUFFER, model_vbo[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float), vertices.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[1]);
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(float), colors.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[2]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(float), normals.data(), GL_DYNAMIC_DRAW);

glBindVertexArray(model_vao);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[2]);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);

Draw loop

s.use();
s.setMat4("model", Rotate * Scale);
s.setMat4("projection", cam.projection());
s.setMat4("view", cam.view());
glBindVertexArray(model_vao);
glDrawArray(GL_TRIANGLES, 0, vertices.size() / 3);

vertex shader

#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec3 normal;

uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;

out vec3 Color;
out vec3 Normal;

void main(){
    Normal = normal;
    Color = color;
    gl_Position = projection * view * model * vec4(position, 1.0);
}

fragment shader

#version 450 core
out vec4 scene_color;
in vec3 Color; // vertex color
in vec3 Normal;
void main(){
    scene_color = vec4(Color,1.0);
}
yys_c
  • 15
  • 6
  • It's called MyMesh. Doesn't that mean you wrote it yourself? So, you are be the person who has to write that function? By the way, vertices don't have different texcoords per face in most formats. – user253751 Mar 24 '22 at 12:16
  • @user253751 I followed the tutorial and used `#define MyMesh #define MyMesh OpenMesh::TriMesh_ArrayKernelT<>`, sorry for the confusion – yys_c Mar 24 '22 at 12:18
  • @user253751 Can I get the index of texcoords of vertex of each face? – yys_c Mar 24 '22 at 12:20
  • Idk, probably. Sorry I'm not an expert in OpenMesh - just pointing out obvious stuff that I do know. You aren't reading the normals per face per vertex, either - is that also a problem? The vertices in one face don't all have to have the same normal, and I bet OpenMesh is averaging them out for you. – user253751 Mar 24 '22 at 12:24
  • Could you show your draw and shaders code ? – Victor Gubin Mar 24 '22 at 12:26
  • @user253751 Yes, I know this problem, so I put many duplicate vertices in my vertices array. If a vertex has three normals, I will put three same vertices in the array with different normals. I want to do the same way with texcoords – yys_c Mar 24 '22 at 12:29
  • @Ok Got it. First of all, [Wavefront](https://en.wikipedia.org/wiki/Wavefront_.obj_file) format don't have texture information and mapping with it. It is provided with additional text file called material library i.e. `.mtl` file. You'll need additional texture option Options::VertexTexCoord – Victor Gubin Mar 26 '22 at 12:18
  • In any case OpenMesh are really legacy C++98 framework. Strongly suggest you to convert your Wavefront to [GLTF](https://www.khronos.org/gltf/) i.e. open in Blender and save as GLTF, as wall as use more modern librarian like [see Asimp tutorial](https://learnopengl.com/Model-Loading/Assimp) – Victor Gubin Mar 26 '22 at 12:18
  • @VictorGubin Thank you very much for your help and suggestion, but the only reason I used OpenMesh is that I need to get every vertex’s adjacent vertices(neighbors). I don’t know if I can get the same thing done in assimp library(I googled it and didn’t find tutorial on getting vertices’ neighbors with assimp) – yys_c Mar 26 '22 at 12:51
  • Assimp doing [mesh optimization internally](https://github.com/assimp/assimp/blob/master/code/PostProcessing/OptimizeMeshes.h). You'll use Index Data Buffer to draw faces, i.e. video memory usage will be minimized. This lib well known and wide used in 3D graphics. – Victor Gubin Mar 26 '22 at 13:18
  • @VictorGubin Thanks again for the valuable information, but actually, I’m doing laplacian deformation, and to do this I need the vertex neighbor info to form a laplacian matrix, and by solving a linear system and I can get every changed vertex and update every vertex in the original model. So I don’t know how to get this if I can’t get the neighbor info of every vertex. Still, I use openmesh only for this reason. Would you mind giving some recommendations or some instructions on how to do this with assimp? I really appreciate it. – yys_c Mar 26 '22 at 13:36
  • @VictorGubin Btw, I have done the algorithm stuff and got it work on my machine with plain model(no texture, only mesh). If you don’t mind taking a look of my shitty code, I will add a attachment to my question. – yys_c Mar 26 '22 at 13:55
  • Ok how about [libigl](https://libigl.github.io/tutorial/) then. It can work with Wavefront out of the box. For GLTF you can load model with Asimp, and then fulfill matrices from Asimp data structures. – Victor Gubin Mar 26 '22 at 15:20
  • 1
    @VictorGubin Thank you very much, I will give it a try. It seems easier to use than openmesh. – yys_c Mar 27 '22 at 03:19

0 Answers0