draw model-based objects using shaders

This commit is contained in:
Josh Holtrop 2011-05-25 15:53:43 -04:00
parent 6e5eafb8d9
commit be307c2c32
2 changed files with 108 additions and 24 deletions

View File

@ -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;

View File

@ -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<string, WFObj::Material>::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)