Search code examples
c++oopopenglglfwglm-math

Opengl GLFW3, Cant update vertices of two object at the same time


So i am trying to make a game where I want to update my player and enemy. enemy and player are squares. I have a square class with VAO, VBO, EBO and vertices where I load my square.

void Square::loadSquare()
{
unsigned int indices[] = {  
    0, 1, 3,   // first triangle
    1, 2, 3    // second triangle
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
 
// bind vertex array object
glBindVertexArray(VAO);

// bind vertex buffer object
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);

// bind element buffer objects
// EBO is stored in the VAO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// registered VBO as the vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

// unbind the VAO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

and draw method:

void Square::drawSquare()
{
// Bind the VAO so OpenGL knows to use it
glBindVertexArray(VAO);
// Draw the triangle using the GL_TRIANGLES primitive
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

Player and Enemy classes are inherited from square class and they have their own update method where I call in my Carte classes update methode.

void Carte::update(){
drawMap();
enemy.update(GrapMap,0);
player.update(GrapMap);
}

In draw map I simply draw my enemy and player.

void Carte::drawMap(){
enemy.drawSquare();
player.drawSquare();
for(auto & wall : walls){
    wall.drawSquare();
}
}

Walls are squares too but in my case I draw therm where I want and I don't have a problem with them. at the end of every update of enemy and player after chancing vertices of them I call

glBindBuffer(GL_ARRAY_BUFFER, VAO);

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); 

When it was only player that I was updating it was working flawlessly. But with enemy I cant see the player but I can see that its vertices are changing accordingly to the key input of the user. When I comment out player and try to update enemy only enemy is not updating but again I can see its vertices changing as it should.

Before creating my Carte object at the main I did this:

// Vertex Shader source code
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
//Fragment Shader source code
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(0.8f, 0.3f, 0.02f, 1.0f);\n"
"}\n\0";


int main()
{
// Initialize GLFW
glfwInit();

// Tell GLFW what version of OpenGL we are using 
// In this case we are using OpenGL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Tell GLFW we are using the CORE profile
// So that means we only have the modern functions
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

// Create a GLFWwindow object of 800 by 800 pixels, naming it "window"
GLFWwindow* window = glfwCreateWindow(1000, 1000, "Window", NULL, NULL);
// Error check if the window fails to create
if (window == NULL)
{
    std::cout << "Failed to create GLFW window" << std::endl;
    glfwTerminate();
    return -1;
}
// Introduce the window into the current context
glfwMakeContextCurrent(window);

//Load GLAD so it configures OpenGL
gladLoadGL();
// Specify the viewport of OpenGL in the Window
// In this case the viewport goes from x = 0, y = 0, to x = 800, y = 800
//glViewport(0, 0, 1400, 1400);



// Create Vertex Shader Object and get its reference
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
// Attach Vertex Shader source to the Vertex Shader Object
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
// Compile the Vertex Shader into machine code
glCompileShader(vertexShader);

// Create Fragment Shader Object and get its reference
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
// Attach Fragment Shader source to the Fragment Shader Object
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
// Compile the Vertex Shader into machine code
glCompileShader(fragmentShader);

// Create Shader Program Object and get its reference
GLuint shaderProgram = glCreateProgram();
// Attach the Vertex and Fragment Shaders to the Shader Program
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
// Wrap-up/Link all the shaders together into the Shader Program
glLinkProgram(shaderProgram);

// Delete the now useless Vertex and Fragment Shader objects
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

In my while loop I am doing this:

// Specify the color of the background
    glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
    // Clean the back buffer and assign the new color to it
    glClear(GL_COLOR_BUFFER_BIT);
    // Tell OpenGL which Shader Program we want to use
    glUseProgram(shaderProgram);
    int keyW = glfwGetKey(window, GLFW_KEY_W);
    int keyA = glfwGetKey(window, GLFW_KEY_A); 
    int keyS = glfwGetKey(window, GLFW_KEY_S);
    int keyD = glfwGetKey(window, GLFW_KEY_D);

    carte.update();
    
    if(keyW)
        deneme.setPlayerDirection(Directions::UP);
    else if(keyA)
        deneme.setPlayerDirection(Directions::LEFT);
    else if(keyS)
        deneme.setPlayerDirection(Directions::DOWN);
    else if(keyD)
        deneme.setPlayerDirection(Directions::RIGHT);

    // Swap the back buffer with the front buffer
    glfwSwapBuffers(window);
    // Take care of all GLFW events
    glfwPollEvents();
    

I don't understand why I can't update my two objects at the same time. Why I cant draw squares as the vertices changes when there is more then one objects vertices are changing.

edit to show how I change my vertices in Player:

if(getDirection() == Directions::UP){
    trans = glm::translate(trans, glm::vec3(0.0f, 0.0002f,   0.0f));
    setCenter(center.first,center.second + 0.0002f);
}
else if (getDirection() == Directions::LEFT){
    trans = glm::translate(trans, glm::vec3(-0.0002f, 0.0f, 0.0f));
    setCenter(center.first-0.0002f,center.second);
}
else if (getDirection() == Directions::DOWN){
    trans = glm::translate(trans, glm::vec3(0.0f, -0.0002f, 0.0f));
    setCenter(center.first,center.second-0.0002f);
}
else if (getDirection() == Directions::RIGHT){
    trans = glm::translate(trans, glm::vec3(0.0002f, 0.0f, 0.0f));
    setCenter(center.first+0.0002f,center.second);
}
else if (getDirection() == Directions::STOP)
    trans = glm::translate(trans, glm::vec3(0.0f, 0.0f, 0.0f));

for(int i=0; i < 4; i ++){
    glm::vec4 tmp = trans * glm::vec4(getVertices()[i],1);
    setVertices(i, tmp.x, tmp.y, tmp.z);
}
glBindBuffer(GL_ARRAY_BUFFER, VAO);

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);

Solution

  • This is not valid code: glBindBuffer(GL_ARRAY_BUFFER, VAO); You're attempting to bind the vertex array object to a vertex buffer location. Those are two completely different types. You probably meant to write glBindBuffer(GL_ARRAY_BUFFER, VBO); but just mistyped it.

    Unless the VAO and VBO happen to have the same value, then you're either updating the wrong buffer, or no buffer at all.