运行期间的

时间:2015-12-31 13:12:27

标签: c++ opengl rotation glsl transform

我有多个对象但不知道如何单独移动或旋转它们。这将是我到目前为止的代码的缩短版本:

const GLchar* vertexSource = "#version 150 core\n"
    "in vec3 position;"
    "uniform mat4 model;"
    "uniform mat4 view;"
    "uniform mat4 proj;"
    "void main() {"
    "   gl_Position = proj * view * model * vec4(position, 1.0);"
    "}";

struct Object {
    // here are the constructors

    vector<Triangle> polys; // Triangle is a struct containing vertex data
    GLuint vao, vbo, ebo;

    // somne other variables and functions
    // ...
};  

void ShaderProgram::AddObject(const vector<Triangle>& polys) {
    objects.push_back(Object(polys));
    Object& obj = objects[objects.size()-1];

    glGenVertexArrays(1, &obj.vao);
    glBindVertexArray(obj.vao);

    // set up vertices and a vertex buffer object for them
    // ...
    glGenBuffers(1, &obj.vbo);
    glBindBuffer(GL_ARRAY_BUFFER, obj.vbo);
    glBufferData(GL_ARRAY_BUFFER, obj.polys.size()*polySize*sizeof(float), vertices, GL_STATIC_DRAW);
    // 'polySize' is just a constant variable to healp me out and 'vertices' is a float array

    // set up element buffer object
    // ...
    glGenBuffers(1, &obj.ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, obj.ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
    // elements is a float array

    GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(posAttrib);
    glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, vertSize*sizeof(float), 0);
    // 'vertSize' is also a constant variable
}

void ShaderProgram::Draw(float dSec) {
    for (Object& it : objects) {
        glBindVertexArray(it.vao);
        // here's some texturing related stuff
        glDrawElements(GL_TRIANGLES, it.vertexCount(), GL_UNSIGNED_INT, 0);
    }
}

void ShaderProgram::Move(Object& obj, glm::vec3 vec) {/*move it somehw*/}
void ShaderProgram::Rotate(Object& obj, glm::vec3 rotPoint, glm::vec3 rot) {/*rotate obj around rotPoint*/}

如果我运行此代码,一切都会完美显示,但我无法找到一种在运行时更改一个特定对象顶点位置的简洁方法。

此外,这与初始问题没有任何关系,但我注意到每当我在笔记本电脑上运行完全相同的代码时,程序在调用glBindFragDataLocation()时会崩溃(它无论我是在Linux还是Windows上运行它都无关紧要。

2 个答案:

答案 0 :(得分:1)

在许多渲染应用程序中,使用了几种不同的坐标系:

  • 对象空间:这是定义顶点的空间。每个模型都有自己的对象坐标和它自己的模型原点。
  • 世界空间:这是场景中所有模型相对于彼此定位的空间。这通常是通过基于场景中的期望位置指定模型矩阵来完成的。

在您的情况下,我会在存储位置的Object结构中添加一个额外的vec3成员。

struct Object {
    //Things you already have

    glm::vec3 loc;
}

然后,您可以在调用glDrawElements之前直接更新模型矩阵。由于已经发出了绘制调用,因此更改此位置的模型矩阵将始终影响正确的对象:

void ShaderProgram::Draw(float dSec) {
    for (Object& it : objects) {
        glBindVertexArray(it.vao);
        // here's some texturing related stuff

        glm::mat4 model_matrix(1.0f);
        glm::translate(model_matrix, it.loc);

        glUniformMatrix4fv(model_uniform_location, 1, GL_FALSE, model_matrix);

        glDrawElements(GL_TRIANGLES, it.vertexCount(), GL_UNSIGNED_INT, 0);
    }
}

另一种选择是将矩阵直接存储在Object类中,这会增加数据大小(并且可能不太直观),但可能会降低运行时成本。

答案 1 :(得分:-1)

Draw函数的当前状态如下所示:

void ShaderProgram::Draw(float dSec) {
    objects[0].location.x += dSec;
    GLint uniModel = glGetUniformLocation(shaderProgram, "model");
    for (Object& it : objects) {
        glBindVertexArray(it.vao);
        glm::mat4 model;
        model = glm::translate(model, it.location);
        glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
        glDrawElements(GL_TRIANGLES, it.vertexCount(), GL_UNSIGNED_INT, 0);
    }
}