Jump to content
  • Advertisement
Sign in to follow this  
metsfan

OpenGL Question about glBufferData

This topic is 2299 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all, I had a question about glBufferData which is probably simple to answer, but I can't seem to figure it out. I have several 3d models in my application that I use over and over. I had the idea to create a Model class, which reads in the mesh, then creates instances of a class called GLSLProgram, which is basically a level of abstraction on top of a GLSL shader program. I want to set it up so that when I create an instance of the model, it will initialize a new shader, and populate the shader program with the vertex, normal, and texel data, then when I draw the model, just update the modelview and projection matrices, and lighting information, so that OpenGL doesn't need to load the same vertex mesh data over and over. This method doesn't seem to be working, however if I re-populate the vertex buffer every time I draw the model, everything works fine. I know people are going to ask for code, so I'll include the Model class.

The main problem is that if I only set the vertex attrib data (which is a wrapper of glBufferData and glVertexAttribPointer) in the Model::CreateInstance method, the model shows up, but the vertices are in the completely wrong place. However, if I set the vertex data in the Model::Draw method, the model shows up fine every time. Can anyone think of why this is happening?

#include "stdafx.h"
#include "Model.h"
#include <FreeImage.h>
Model::Model(std::string filename)
{
Initialize(filename, "model_basic.vert", "model_basic.frag", ModelType3DS);
}
Model::Model(std::string filename, std::string vertexShader, std::string fragmentShader)
{
Initialize(filename, vertexShader, fragmentShader, ModelType3DS);
}
Model::Model(std::string filename, std::string vertexShader, std::string fragmentShader, ModelType type)
{
Initialize(filename, vertexShader, fragmentShader, type);
}
void Model::Initialize(std::string filename, std::string vertexShader, std::string fragmentShader, ModelType type)
{
m_TotalFaces = 0;
m_VertexShader = vertexShader;
m_FragmentShader = fragmentShader;

m_model = lib3ds_file_load(filename.c_str());
// If loading the model failed, we throw an exception
if(!m_model)
{
throw strcat("Unable to load ", filename.c_str());
}
bbox = new BoundingBox();
glGenVertexArrays(1, &m_vaoHandle);
}
// Destructor
Model::~Model()
{
glDeleteBuffers(1, &m_vaoHandle);
if(m_model != NULL)
{
lib3ds_file_free(m_model);
}
for(int i = 0; i < m_Shaders.size(); i++) {
delete m_Shaders;
}
}
void Model::CreateInstance()
{
GLSLProgram *shader = new GLSLProgram(m_VertexShader, m_FragmentShader, 3);
if(shader->compile()) {
if(shader->link()) {

m_Positions.push_back(vec4());
m_Angles.push_back(0);
m_Scales.push_back(0);
shader->use();
shader->setAttribData("VertexPosition", vertices, sizeof(Lib3dsVector) * 3 * m_TotalFaces, GL_STATIC_DRAW);
shader->setAttribData("VertexNormal", normals, sizeof(Lib3dsVector) * 3 * m_TotalFaces, GL_STATIC_DRAW);
shader->setAttribData("VertexTexCoord", texels, sizeof(Lib3dsTexel) * 3 * m_TotalFaces, GL_STATIC_DRAW);
m_Shaders.push_back(shader);
}
}
}
void Model::ApplyTexture(int index, std::string textureFile, FREE_IMAGE_FORMAT type, GLenum texNum, int texId)
{
if(index < m_Shaders.size()) {
Util::load_texture(m_Shaders[index], textureFile, type, texNum, texId, "Tex1");
}
}
// Copy vertices and normals to the memory of the GPU
void Model::ReadData()
{
assert(m_model != NULL);

// Calculate the number of faces we have in total
GetFaces();

// Allocate memory for our vertices and normals
vertices = new Lib3dsVector[m_TotalFaces * 3];
normals = new Lib3dsVector[m_TotalFaces * 3];
texels = new Lib3dsVector[m_TotalFaces * 2];
Lib3dsMesh * mesh;
unsigned int FinishedFaces = 0;
// Loop through all the meshes
for(mesh = m_model->meshes;mesh != NULL;mesh = mesh->next)
{
lib3ds_mesh_calculate_normals(mesh, &normals[FinishedFaces*3]);
// Loop through every face
for(unsigned int cur_face = 0; cur_face < mesh->faces;cur_face++)
{
Lib3dsFace * face = &mesh->faceL[cur_face];
for(unsigned int i = 0;i < 3;i++)
{
float *pos = mesh->pointL[face->points].pos;
/*vec4 pos_vec = vec4(pos[0], pos[1], pos[2], 1.0);
pos_vec = translate * pos_vec;
pos[0] = pos_vec.x;
pos[1] = pos_vec.y;
pos[2] = pos_vec.z;*/
memcpy(&vertices[FinishedFaces*3 + i], pos , sizeof(Lib3dsVector));
float *texel = mesh->texelL[face->points];
if(texel) {
memcpy(&texels[FinishedFaces*2 + i], texel, sizeof(Lib3dsTexel));
}
bbox->AddPoint(vec3(pos[0], pos[1], pos[2]));
}
FinishedFaces++;
}
}
bbox->Calculate();
lib3ds_file_free(m_model);
m_model = NULL;
}
// Count the total number of faces this model has
void Model::GetFaces()
{
assert(m_model != NULL);

m_TotalFaces = 0;
Lib3dsMesh * mesh;
// Loop through every mesh
for(mesh = m_model->meshes;mesh != NULL;mesh = mesh->next)
{
// Add the number of faces this mesh has to the total faces
m_TotalFaces += mesh->faces;
}
}
// Render the model using Vertex Buffer Objects
void Model::Draw(int index, glm::mat4 modelViewMatrix, glm::mat4 projectionMatrix, glm::mat3 normalMatrix)
{
if(index < m_Shaders.size()) {
GLSLProgram *m_Shader = m_Shaders[index];
m_Shader->use();
m_Shader->setUniform("ModelViewMatrix", modelViewMatrix);
m_Shader->setUniform("NormalMatrix", normalMatrix);
m_Shader->setUniform("ProjectionMatrix", projectionMatrix);
m_Shader->setUniform("MVP", projectionMatrix * modelViewMatrix);
vec3 Kd = vec3(139/255.0f, 119/255.0f, 101/255.0f);
m_Shader->setUniform("Kd", Kd);
//program->setUniform("Ld", Kd);
vec3 Ka = vec3(139/255.0f, 119/255.0f, 101/255.0f);
m_Shader->setUniform("Ka", Ka);
vec3 Ks = vec3(1.0, 1.0, 1.0);
m_Shader->setUniform("Ks", Ks);
vec4 LightPosition = vec4(0.0f, 0.0f, 0.0f, 0.0f);
//LightPosition = projection * modelview * LightPosition;
m_Shader->setUniform("LightPosition", LightPosition);
vec3 LightIntensity = vec3(1.0f, 1.0f, 1.0f);
m_Shader->setUniform("LightIntensity", LightIntensity);
m_Shader->setUniform("Shininess", 3.0f);
m_Shader->setAttribData("VertexPosition", vertices, sizeof(Lib3dsVector) * 3 * m_TotalFaces, GL_STATIC_DRAW);
m_Shader->setAttribData("VertexNormal", normals, sizeof(Lib3dsVector) * 3 * m_TotalFaces, GL_STATIC_DRAW);
m_Shader->setAttribData("VertexTexCoord", texels, sizeof(Lib3dsTexel) * 2 * m_TotalFaces, GL_STATIC_DRAW);
//glBindVertexArray(m_vaoHandle);
glDrawArrays(GL_TRIANGLES, 0, m_TotalFaces * 3);
}
}
void Model::SetPosition(int index, vec3 newPosition)
{
if(m_Positions.size() > index) {
m_Positions[index] = vec4(newPosition, 1.0f);
}
}
vec4 Model::GetPosition(int index)
{
if(m_Positions.size() > index) {
return m_Positions[index];
}
return vec4();
}
void Model::SetAngle(int index, float angle)
{
if(m_Angles.size() > index) {
m_Angles[index] = angle;
}
}
float Model::GetAngle(int index)
{
if(m_Angles.size() > index) {
return m_Angles[index];
}
return 0;
}
void Model::SetScale(int index, float scale)
{
if(m_Scales.size() > index) {
m_Scales[index] = scale;
}
}
float Model::GetScale(int index)
{
if(m_Scales.size() > index) {
return m_Scales[index];
}
return 0;
}

Share this post


Link to post
Share on other sites
Advertisement
Nevermind, solved the issue, the issue was the way I was using Vertex Array Objects, having each model have its own VAO solved this issue.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!