我有一个从OBJ文件加载的多维数据集。当我的位置(0,0,0)一切正常。立方体渲染,我的赋予它速度的函数将立方体移动到屏幕上。但是,如果在进入我渲染和计算速度变化的while循环之前将立方体的位置更改为(0,0,0)以外的其他位置,则立方体永远不会渲染。这是我第一次尝试在每次渲染帧时重新加载顶点,而我假设我搞砸了一些东西 - 但是我已经查看了其他代码并且无法弄清楚是什么。 / p>
这是我的主要功能:
int main()
{
#ifdef TESTING
testing();
exit(0);
#endif
setupAndInitializeWindow(768, 480, "Final Project");
TriangleTriangleCollision collisionDetector;
Asset cube1("cube.obj", "vertexShader.txt", "fragmentShader.txt");
cube1.position = glm::vec3(0.0, 2.0, 0.0);
cube1.velocity = glm::vec3(0.0, -0.004, 0.0);
MVP = projection * view * model;
do{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
moveAsset(cube1);
renderAsset(cube1);
glfwSwapBuffers(window);
glfwPollEvents();
} while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
glfwTerminate();
return 0;
}
我的moveAsset功能:
void moveAsset(Asset &asset)
{
double currentTime = glfwGetTime();
asset.position.x += (asset.velocity.x * (currentTime - asset.lastTime));
asset.position.y += (asset.velocity.y * (currentTime - asset.lastTime));
asset.position.z += (asset.velocity.z * (currentTime - asset.lastTime));
for (glm::vec3 &vertex : asset.vertices)
{
glm::vec4 transformedVector = glm::translate(glm::mat4(1.0f), asset.position) * glm::vec4(vertex.x, vertex.y, vertex.z, 1);
vertex = glm::vec3(transformedVector.x, transformedVector.y, transformedVector.z);
}
asset.lastTime = glfwGetTime();
}
void renderAsset(Asset asset)
{
glUseProgram(asset.programID);
GLuint MatrixID = glGetUniformLocation(asset.programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, asset.vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, asset.vertices.size() * sizeof(glm::vec3), &asset.vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, asset.vertices.size());
glDisableVertexAttribArray(0);
}
我的模型,视图和投影矩阵定义为:
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(glm::vec3(5, 5, 10),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0));
glm::mat4 projection = glm::perspective(45.0f, (float) _windowWidth / _windowHeight, 0.1f, 100.0f);
最后,我的Asset struct:
struct Asset
{
Asset() { }
Asset(std::string assetOBJFile, std::string vertexShader, std::string fragmentShader)
{
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
programID = LoadShaders(vertexShader.c_str(), fragmentShader.c_str());
// Read our .obj file
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;
loadOBJ(assetOBJFile.c_str(), vertices, uvs, normals);
// Load it into a VBO
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
//velocity = glm::vec3(0.0, 1.0, 1.0);
velocity = glm::vec3(0.0, 0.0, 0.0);
position = glm::vec3(0.0, 0.0, 0.0);
lastTime = glfwGetTime();
}
GLuint vertexArrayID;
GLuint programID;
GLuint vertexbuffer;
std::vector<glm::vec3> faces;
std::vector<glm::vec3> vertices;
glm::vec3 velocity;
double lastTime;
glm::vec3 position;
};
答案 0 :(得分:0)
您似乎在每次迭代时将当前asset.position
添加到顶点位置 ,替换之前的位置。来自moveAsset()
函数:
for (glm::vec3 &vertex : asset.vertices)
{
glm::vec4 transformedVector = glm::translate(glm::mat4(1.0f), asset.position) *
glm::vec4(vertex.x, vertex.y, vertex.z, 1);
vertex = glm::vec3(transformedVector.x, transformedVector.y, transformedVector.z);
}
暂时忽略速度,并假设原始顶点位于(0,0,0),您将在第一次迭代时将其移动到asset.position
。然后在第二次迭代时再次添加asset.position
,将其置于2 * asset.position
。然后在第三次迭代中,再次将asset.position
添加到此当前位置,结果为3 * asset.position
。因此,在n
步后,顶点将在n * asset.position
附近。即使您的对象最初可见,它也会在您可以闪烁之前移出可见范围。
要使原始策略有效,最直接的方法是拥有两个顶点列表。一个列表包含您永远不会更改的原始对象坐标。然后在绘制之前,构建第二个顶点列表,计算为原始顶点加上当前asset.position
的总和,并使用第二个列表进行渲染。
整个事情是......不是很OpenGL。实际上不需要修改CPU上的顶点坐标。您可以在顶点着色器中应用变换的平移部分。您已经有了模型矩阵。您可以简单地将asset.position
的翻译放入模型矩阵中,然后重新计算MVP矩阵。您已经有glUniformMatix4fv()
调用将新矩阵传递到renderAsset()
函数中的着色器程序。