From be307c2c324507dab4078ed8389b96d328afc9fc Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Wed, 25 May 2011 15:53:43 -0400 Subject: [PATCH] draw model-based objects using shaders --- src/Engine.h | 3 +- src/Engine_Object.cc | 129 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 108 insertions(+), 24 deletions(-) diff --git a/src/Engine.h b/src/Engine.h index 65d5a4a..fdf40b9 100644 --- a/src/Engine.h +++ b/src/Engine.h @@ -120,7 +120,8 @@ class Engine bool m_enable_blending; /* for "pre-loaded" objects */ - int * m_display_list_refcnt; + WFObj * m_obj; + int * m_obj_refcnt; /* for "managed" objects */ OdeWorld::GeomType m_geom_type; diff --git a/src/Engine_Object.cc b/src/Engine_Object.cc index cf19feb..b5face4 100644 --- a/src/Engine_Object.cc +++ b/src/Engine_Object.cc @@ -42,19 +42,20 @@ Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending, } m_is_static = is_static; m_enable_blending = enable_blending; - m_display_list = obj->render(true, enable_blending); const float * obj_aabb = obj->getAABB(); for (int i = 0; i < 6; i++) m_aabb[i] = scale * obj_aabb[i]; - m_display_list_refcnt = new int; - *m_display_list_refcnt = 1; m_is_visible = true; m_scale = scale; m_is_scaled = ! (fabs(scale - 1.0) < 0.0001); + m_display_list = 0; m_is_managed = false; m_mass = 0.0; m_mass_is_set = false; m_gravity_mode = true; + m_obj = obj; + m_obj_refcnt = new int; + *m_obj_refcnt = 1; } /* used for "managed" objects with one geom */ @@ -70,7 +71,6 @@ Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending, m_scale = 1.0f; m_is_scaled = false; m_display_list = 0; - m_display_list_refcnt = NULL; if (m_is_reference) { m_ode_object = NULL; @@ -92,6 +92,8 @@ Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending, m_mass = 0.0; m_mass_is_set = false; m_gravity_mode = true; + m_obj = NULL; + m_obj_refcnt = NULL; } /* used to clone objects */ @@ -106,13 +108,7 @@ Engine::Object::Object(const Engine::Object & orig) m_is_scaled = orig.m_is_scaled; m_phy = orig.m_phy; m_is_managed = orig.m_is_managed; - if (m_is_managed) - m_display_list = 0; - else - m_display_list = orig.m_display_list; - m_display_list_refcnt = orig.m_display_list_refcnt; - if (m_display_list_refcnt != NULL) - (*m_display_list_refcnt)++; + m_display_list = 0; m_geom_type = orig.m_geom_type; m_args = orig.m_args; for (int i = 0; i < 4; i++) @@ -142,26 +138,26 @@ Engine::Object::Object(const Engine::Object & orig) } m_gravity_mode = orig.m_gravity_mode; setGravityMode(m_gravity_mode); + m_obj = orig.m_obj; + m_obj_refcnt = orig.m_obj_refcnt; + if (m_obj_refcnt) + (*m_obj_refcnt)++; } Engine::Object::~Object() { if (m_ode_object != NULL) delete m_ode_object; - if (m_display_list_refcnt != NULL) - { - (*m_display_list_refcnt)--; - if (*m_display_list_refcnt < 1) - { - /* we hold the last reference to the OpenGL display list */ - delete m_display_list_refcnt; - glDeleteLists(m_display_list, 1); - } - } - else + if (m_display_list != 0) { glDeleteLists(m_display_list, 1); } + if (m_obj_refcnt != NULL) + { + (*m_obj_refcnt)--; + if (*m_obj_refcnt < 1) + delete m_obj; + } } void Engine::Object::createManagedObject() @@ -522,7 +518,94 @@ void Engine::Object::draw() } checkGLError(); - glCallList(m_display_list); + + if (m_is_managed) + { + glCallList(m_display_list); + } + else + { + GLuint program = m_programs[PROG_OBJ]; + glUseProgram(program); + glEnableVertexAttribArray(ATTRIBUTE_OBJ_POS); + glEnableVertexAttribArray(ATTRIBUTE_OBJ_NORMAL); + int stride = m_obj->getStride(); + glVertexAttribPointer(ATTRIBUTE_OBJ_POS, 3, GL_FLOAT, GL_FALSE, + stride, (GLvoid *) m_obj->getVertexOffset()); + glVertexAttribPointer(ATTRIBUTE_OBJ_NORMAL, 3, GL_FLOAT, GL_FALSE, + stride, (GLvoid *) m_obj->getNormalOffset()); + if (m_obj->doTextures()) + { + glVertexAttribPointer(ATTRIBUTE_OBJ_TEX_TEX_COORD, + 2, GL_FLOAT, GL_FALSE, + stride, (GLvoid *) m_obj->getTextureCoordOffset()); + } + for (map::iterator it = + m_obj->getMaterials().begin(); + it != m_obj->getMaterials().end(); + it++) + { + WFObj::Material & m = it->second; + if (m.flags & WFObj::Material::TEXTURE_BIT) + { + if (program != m_programs[PROG_OBJ_TEX]) + { + program = m_programs[PROG_OBJ_TEX]; + glUseProgram(program); + glEnableVertexAttribArray(ATTRIBUTE_OBJ_TEX_TEX_COORD); + } + } + else + { + if (program != m_programs[PROG_OBJ]) + { + program = m_programs[PROG_OBJ]; + glUseProgram(program); + glDisableVertexAttribArray(ATTRIBUTE_OBJ_TEX_TEX_COORD); + } + } + if (m.flags & WFObj::Material::SHININESS_BIT) + { + if (program == m_programs[PROG_OBJ_TEX]) + glUniform1f( + m_uniforms_obj_tex[UNIFORM_OBJ_TEX_SHININESS], + m.shininess); + else + glUniform1f(m_uniforms_obj[UNIFORM_OBJ_SHININESS], + m.shininess); + } + if (m.flags & WFObj::Material::AMBIENT_BIT) + { + if (program == m_programs[PROG_OBJ_TEX]) + glUniform4fv( + m_uniforms_obj_tex[UNIFORM_OBJ_TEX_AMBIENT], + 1, &m.ambient[0]); + else + glUniform4fv(m_uniforms_obj[UNIFORM_OBJ_AMBIENT], + 1, &m.ambient[0]); + } + if (m.flags & WFObj::Material::DIFFUSE_BIT) + { + if (program != m_programs[PROG_OBJ_TEX]) + glUniform4fv(m_uniforms_obj[UNIFORM_OBJ_DIFFUSE], + 1, &m.diffuse[0]); + } + if (m.flags & WFObj::Material::SPECULAR_BIT) + { + if (program == m_programs[PROG_OBJ_TEX]) + glUniform4fv( + m_uniforms_obj_tex[UNIFORM_OBJ_TEX_SPECULAR], + 1, &m.specular[0]); + else + glUniform4fv(m_uniforms_obj[UNIFORM_OBJ_SPECULAR], + 1, &m.specular[0]); + } + glDrawElements(GL_TRIANGLES, m.num_vertices, + GL_UNSIGNED_SHORT, + (GLvoid *) (sizeof(GLushort) * m.first_vertex)); + } + } + checkGLError(); if (m_is_scaled)