-1

I'm making a small game engine for vector graphics in OpenGL, and it is already broken in the early stages. I had it working with all the data for one object in the main.cpp file, but once I moved all that code into a class called Object, it completely stopped working. I don't have an old version of the code from before I implemented the object system, but all the code right now is at https://github.com/DJLevel3/Vector2.0. I think it's a problem with the initialization code (Object::genVAO() in src/object.cpp) but I can't figure out the problem.

I'll copy the code I think is relevant here, but there's a LOT of code in the files so I'll be removing all the unused methods and the methods with obvious functions. I'd recommend looking at the Github for the full files. Also, assume all headers have been included when needed and protected from duplicate includes.

Last thing before I post heaps of code, the things I think the problem is most likely in are closer to the top and the less likely ones are towards the bottom.

Source Code

Important structs used in most of the files:

struct vertex {
    glm::vec3 pos;
    glm::vec3 color;
};
struct shader {
    GLuint program;
    GLuint mvp;
    GLint attribIDPosition;
    GLint attribIDColor;
};

(Trimmed) object.cpp:

using namespace vector2;

Object::Object( std::vector<vertex> v, std::vector<GLuint> i, glm::vec3 position, glm::quat rotation, glm::vec3 scale )
{
    vertices = v;
    indices = i;
    size = i.size()/3;
    pos = position;
    rot = rotation;
    scl = scale;
    genMatrix();
}

void Object::genVAO(shader s)
{
    vertex v[vertices.size()];
    std::copy(vertices.begin(), vertices.end(), v);

    GLuint i[indices.size()];
    std::copy(indices.begin(), indices.end(), i);

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

    GLuint vertexBuffer, indexBuffer;
    glGenBuffers( 1, &vertexBuffer );
    glGenBuffers( 1, &indexBuffer );

    glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW );

    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(i), i, GL_STATIC_DRAW );

    glVertexAttribPointer( s.attribIDPosition, 3, GL_FLOAT, false, sizeof(vertex), MEMBER_OFFSET(vertex,pos) );
    glEnableVertexAttribArray( s.attribIDPosition );

    glVertexAttribPointer( s.attribIDColor, 3, GL_FLOAT, false, sizeof(vertex), MEMBER_OFFSET(vertex,color) );
    glEnableVertexAttribArray( s.attribIDColor );

    glBindVertexArray( 0 );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
    glDisableVertexAttribArray( s.attribIDPosition );
    glDisableVertexAttribArray( s.attribIDColor );
}

void Object::genMatrix()
{
    modelMatrix = glm::translate(glm::mat4(), pos) * glm::toMat4(rot) * glm::scale(scl);
}

void Object::setVertices(std::vector<vertex> v)
{
    vertices = v;
}

void Object::setIndices(std::vector<GLuint> i)
{
    indices = i;
    size = i.size()/3;
}

(Trimmed) object.hpp

namespace vector2 {
    class Object {
    protected:
        std::vector<vertex> vertices;
        std::vector<GLuint> indices;

        int size;

        GLuint vao = 0;

        glm::vec3 pos = {0,0,0};
        glm::quat rot = {1,0,0,0};
        glm::vec3 scl = {1,1,1};
        glm::mat4 modelMatrix;
    public:
        Object( std::vector<vertex> v, std::vector<GLuint> i, glm::vec3 position, glm::quat rotation, glm::vec3 scale );

        void setVertices(std::vector<vertex> v);
        void setIndices(std::vector<GLuint> i);

        void genVAO( shader s );
        void genMatrix();
    };
}

**(Trimmed) render.cpp

using namespace vector2;

void vector2::drawModel(Object o, shader s)
{
    glBindVertexArray( o.getVAO() );
    glUseProgram( s.program );

    glm::mat4 mvp = g_Camera.GetProjectionMatrix() * g_Camera.GetViewMatrix() * o.getMatrix();
    glUniformMatrix4fv( s.mvp, 1, GL_FALSE, glm::value_ptr(mvp) );

    glDrawElements( GL_TRIANGLES, o.getSize(), GL_UNSIGNED_INT, BUFFER_OFFSET(0) );

    glUseProgram(0);
    glBindVertexArray(0);
}

(Trimmed) main.cpp

using namespace vector2;

shader vecShader;
std::vector<vertex> shipVertices = {
        {glm::vec3( 0.00,  2.00, -1.00), glm::vec3(0,1,0.2)},  // 0
        {glm::vec3( 0.00,  0.00,  4.00), glm::vec3(0,1,0.2)},  // 1
        {glm::vec3( 3.00,  0.00, -5.00), glm::vec3(0,1,0.2)},  // 2
        {glm::vec3( 0.00, -1.50, -2.00), glm::vec3(0,1,0.2)},  // 3
        {glm::vec3(-3.00,  0.00, -5.00), glm::vec3(0,1,0.2)},  // 4
        {glm::vec3( 0.65, -1.50, -5.00), glm::vec3(0,1,0.2)},  // 5
        {glm::vec3(-0.65, -1.50, -5.00), glm::vec3(0,1,0.2)},  // 6
        {glm::vec3( 0.65,  0.00, -5.00), glm::vec3(0,1,0.2)},  // 7
        {glm::vec3(-0.65,  0.00, -5.00), glm::vec3(0,1,0.2)}   // 8
};
int shipSize = 8 * 3;
std::vector<GLuint> shipIndices = {
        0,     1,    2,  // 0
        0,     1,    4,  // 1
        3,     1,    2,  // 2
        3,     1,    4,  // 3
        2,     1,    4,  // 4
        3,     5,    6,  // 5
        3,     5,    7,  // 6
        3,     6,    8,  // 7
};
Object ship;

void DisplayGL()
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    drawModel(ship, vecShader);

    glutSwapBuffers();
}

int main( int argc, char* argv[] )
{
    InitGL(argc, argv);
    InitGLEW();

    GLuint vertexShaderV,geoShaderV,fragmentShaderV;

    vertexShaderV = LoadShader( GL_VERTEX_SHADER, "../resources/shaders/vecshader/vertex.glsl" );
    geoShaderV = LoadShader( GL_GEOMETRY_SHADER, "../resources/shaders/vecshader/geometry.glsl" );
    fragmentShaderV = LoadShader( GL_FRAGMENT_SHADER, "../resources/shaders/vecshader/fragment.glsl" );

    std::vector<GLuint> shadersV;

    shadersV.push_back(vertexShaderV);
    shadersV.push_back(geoShaderV);
    shadersV.push_back(fragmentShaderV);

    vecShader.program = CreateShaderProgram( shadersV );
    assert( vecShader.program != 0 );

    vecShader.attribIDPosition = glGetAttribLocation( vecShader.program, "inPosition" );
    vecShader.attribIDColor = glGetAttribLocation( vecShader.program, "inColor" );
    vecShader.mvp = glGetUniformLocation( vecShader.program, "mvp" );

    ship = Object(shipVertices, shipIndices, (glm::vec3){0,0,0}, (glm::quat){1,0,0,0}, (glm::vec3){1,1,1});
    ship.genVAO(vecShader);
    ship.genMatrix();

    glutMainLoop();
}

CreateShaderProgram and LoadShader both work correctly (loading shaders from files and creating a program) and have not been modified since before I broke the code.

Shaders

vertex.glsl

#version 330 core

layout(location=0) in vec3 inPosition;
layout(location=1) in vec3 inColor;

out vec4 gsin;

uniform mat4 mvp;

void main()
{
    gl_Position = mvp * vec4(inPosition, 1);
    gsin = vec4(inColor, 1);
}

fragment.glsl

#version 330 core
layout (triangles) in;
layout (line_strip, max_vertices = 4) out;

in vec4 gsin[];

out vec4 fColor;

void main() {
    fColor = gsin[0];
    gl_Position = gl_in[0].gl_Position;
    EmitVertex();
    fColor = gsin[1];
    gl_Position = gl_in[1].gl_Position;
    EmitVertex();
    fColor = gsin[2];
    gl_Position = gl_in[2].gl_Position;
    EmitVertex();
    fColor = gsin[0];
    gl_Position = gl_in[0].gl_Position;
    EmitVertex();
    EndPrimitive();
}

fragment.glsl

#version 330 core
in vec4 fColor;

layout(location=0) out vec4 outColor;

void main()
{
    outColor = fColor;
}
  • You are rendering too few elements. glDrawArrays expects the number of indices, not the number of triangles. Also note, that you are copying a lot of objects all over the place. For example, why copy the vertex vector into a temporary array before passing it to GL? Also: Each calls to `drawModel` creates a copy of your object; each method which takes a std::vector will copy the vector once. You should really have a look into passing references or pointer instead of copying your objects. – BDL Apr 23 '21 at 22:11
  • Doesn't the vertex array need to be an array? Or can it be a vector? If it can be a vector then that changes a lot. – Zachary Berkowitz Apr 23 '21 at 22:47
  • The vertex data is a pointer to some memory. Whether the memory comes from an array or from a vector doesn't matter. – BDL Apr 23 '21 at 23:04
  • I tried using the vectors straight, it threw up a bunch of errors. Also, I found out that it's actually the model matrix that's causing problems. Not sure why. – Zachary Berkowitz Apr 23 '21 at 23:20

1 Answers1

0

So it turns out that I'm really stupid. in object.cpp, I created the model matrix incorrectly by using glm::mat4() instead of glm::mat4(1.0). The rest of the code was working exactly as intended, but the M in MVP wasn't working. Fixed it and everything works now.