【发布时间】:2020-01-24 23:29:33
【问题描述】:
我想实现一个 obj 加载器,它可以从 blender 导出的 obj 文件中获取“v”(顶点)、“vt”(纹理)、“vn”(法线)和“f”(面)坐标在我的程序上渲染它。但是,在实施之后,我发现它存在问题。当我创建它时没有任何显示。现在,自从我开始,网格代码对我来说一直是个问题,所以我希望有人能找到我无法找到的东西。不仅如此,纹理代码状态(在终端中)Trying to access the pixels of an empty image。但是,我给它的图像有像素,我完全不知道为什么会这样。
// Chest.cpp
objLoader.loadObjModel("res/models/test.obj");
mesh.loadToVAO(objLoader.getVertices(), objLoader.getTextures(), objLoader.getNormals(), objLoader.getIndices());
mesh.loadTexture(Texture::get("res/images/wallpaper.png"));
program = Program::get(BASIC_VERTEX_SHADER, BASIC_FRAGMENT_SHADER);
这会从test.obj 加载一个obj 模型,然后在mesh.loadToVAO 中获取顶点、纹理、法线和索引。然后网格也得到纹理位置。
// Mesh.cpp // Loading
void Mesh::loadToVAO(std::vector<glm::vec3> vertices, std::vector<glm::vec2> textures, std::vector<glm::vec3> normals, std::vector<int> indices) {
// create a VAO
GLuint vaoID = createVAO();
indicesSize = indices.size();
bindIndicesBuffer(indices.data(), indicesSize);
// Store the data in attribute lists
storeDataInAttrubeList(0, 3, &vertices[0], vertices.size() * sizeof(glm::vec3));
storeDataInAttrubeList(1, 2, &textures[0], textures.size() * sizeof(glm::vec2));
storeDataInAttrubeList(2, 3, &normals[0], normals.size() * sizeof(glm::vec3));
unbindVAO();
}
// Rendering
void Mesh::renderVAO() {
// Texture
texture->useTexture();
// Binding
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO);
// Rendering
glDrawElements(GL_TRIANGLES, indicesSize, GL_UNSIGNED_INT, 0);
// Unbinding
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// createVAO/storeDataInAttrubeList/bindIndicesBuffer
GLuint Mesh::createVAO() {
GLuint vaoID;
glGenVertexArrays(1, &vaoID);
VAO = vaoID;
glBindVertexArray(vaoID);
return vaoID;
}
void Mesh::storeDataInAttrubeList(GLuint attribNumber, int attribSize, void* data, int dataSize) {
GLuint vboID;
// Create a new buffer
glGenBuffers(1, &vboID);
// Store the buffer in the list
VBO = vboID;
// Bind the buffer to use it
glBindBuffer(GL_ARRAY_BUFFER, vboID);
// Store the data in the buffer
glBufferData(GL_ARRAY_BUFFER, dataSize, data, GL_STATIC_DRAW);
// Tell OpenGL how and where to store this VBO in the VAO
glVertexAttribPointer(attribNumber, attribSize, GL_FLOAT, GL_FALSE, 0, nullptr);
}
void Mesh::bindIndicesBuffer(int* indices, int& count) {
GLuint vboID;
// Generate a buffer and bind it for use
glGenBuffers(1, &vboID);
// Store the buffer in the list
VBO = vboID;
// Bind the buffer to use it
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
// Store the indices in the buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * count, indices, GL_STATIC_DRAW);
}
这会遍历每一行并找到合适的坐标。
while (fgets(line, 256, file) != NULL) {
token = NULL;
type = strtok_s(line, " ", &token);
// Vertex
if (type[0] == 'v' && type[1] == NULL) {
x = strtod(token, &stop);
token = stop + 1;
y = strtod(token, &stop);
token = stop + 1;
z = strtod(token, &stop);
vertices.push_back(glm::vec3(x, y, z));
}
// Textures
else if (type[0] == 'v' && type[1] == 't') {
x = strtod(token, &stop);
token = stop + 1;
y = 1 - strtod(token, &stop);
tempTextures.push_back(glm::vec2(x, y));
}
// Normals
else if (type[0] == 'v' && type[1] == 'n') {
x = strtod(token, &stop);
token = stop + 1;
y = strtod(token, &stop);
token = stop + 1;
z = strtod(token, &stop);
tempNormals.push_back(glm::vec3(x, y, z));
}
// Faces
else if (type[0] == 'f') {
if (indices.size() == 0) {
// Set size of the array
textures.resize(vertices.size());
normals.resize(vertices.size());
}
// Process vertices data
processVertices(token, indices, tempTextures, textures, tempNormals, normals);
}
}
// This method process the vertice and indice information
void OBJLoader::processVertices(char* vertexData, std::vector<int>& indices, std::vector<glm::vec2>& tempTextures,
std::vector<glm::vec2>& textures, std::vector<glm::vec3>& tempNormals, std::vector<glm::vec3>& normals) {
char* stop;
int vertexPointer;
for (unsigned int i = 0; i < 3; i++) {
// Get and store index
vertexPointer = strtol(vertexData, &stop, 10) - 1;
indices.push_back(vertexPointer);
vertexData = stop + 1;
textures[vertexPointer] = tempTextures[strtol(vertexData, &stop, 10) - 1];
vertexData = stop + 1;
normals[vertexPointer] = tempNormals[strtol(vertexData, &stop, 10) - 1];
vertexData = stop + 1;
}
}
在Chest.cpp你可以看到我正在调用一个叫get(something)的方法,就是这个样子
std::vector<glm::vec3> getVertices() { return vertices; } // Note that vertices and etc. are vectors
最后,这不是渲染还是只是没有创建? 我知道代码相当长,但是我不完全知道哪些部分对我的问题最重要或最负责。
【问题讨论】:
标签: c++ opengl glm-math wavefront