00001 00005 /* Copyright © 2009, 2010 James Legg. 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 */ 00011 #include "DrawableMesh.h" 00012 00013 #include <GL/glew.h> 00014 #include <GL/gl.h> 00015 00016 #include <Debug.h> 00017 00018 // Remove to force vertex arrays instead of vertex buffer objects. 00019 #define USE_VERTEX_BUFFER_OBJECTS 00020 // If USE_VERTEX_BUFFER_OBJECTS is defined, VBOs are used only when supported. 00021 // When VBOs are not supported vertex arrays are used anyway. 00022 00023 namespace Track 00024 { 00025 00026 DrawableMesh::DrawableMesh(std::istream & source, RenderMode render_mode) 00027 : MeshFaces(source) 00028 , display_list(0) 00029 , render_mode(render_mode) 00030 { 00031 } 00032 00033 DrawableMesh::DrawableMesh(const MeshFaces & mesh, RenderMode render_mode) 00034 : MeshFaces(mesh) 00035 , display_list(0) 00036 , render_mode(render_mode) 00037 { 00038 } 00039 00040 DrawableMesh::DrawableMesh(std::string filename, RenderMode render_mode) 00041 : MeshFaces(filename) 00042 , display_list(0) 00043 , render_mode(render_mode) 00044 { 00045 } 00046 00047 DrawableMesh::DrawableMesh(RenderMode render_mode) 00048 : display_list(0) 00049 , render_mode(render_mode) 00050 { 00051 } 00052 00053 DrawableMesh::~DrawableMesh() 00054 { 00055 } 00056 00057 void DrawableMesh::draw() const 00058 { 00059 if (!display_list) 00060 { 00061 // we haven't made the display list for the mesh yet. Do that now. 00062 make_cache(); 00063 } 00064 glCallList(display_list); 00065 } 00066 00067 void DrawableMesh::make_cache() const 00068 { 00069 if (!display_list) 00070 { 00071 list_handle = boost::shared_ptr<unsigned int>(make_list(), delete_list); 00072 } 00073 } 00074 00075 unsigned int * DrawableMesh::make_list() const 00076 { 00077 // OpenGL vertex buffer names for mesh data. 00078 unsigned int buffer_name; 00079 std::vector<GLfloat> data; 00080 // normal, tex u, tex v, position; for 3 vertices a face 00081 const unsigned int elements_per_vertex = 8; 00082 data.reserve(faces.size() * 3 * (elements_per_vertex)); 00083 for (std::vector<MeshFaces::Face>::const_iterator it = faces.begin(); 00084 it != faces.end(); 00085 it++) 00086 { 00087 #define do_vert(v)\ 00088 data.push_back(v.normal.getX());\ 00089 data.push_back(v.normal.getY());\ 00090 data.push_back(v.normal.getZ());\ 00091 data.push_back(v.texture_coord_u);\ 00092 data.push_back(v.texture_coord_v);\ 00093 data.push_back(vertices_position[v.vertex_index].getX());\ 00094 data.push_back(vertices_position[v.vertex_index].getY());\ 00095 data.push_back(vertices_position[v.vertex_index].getZ()); 00096 00097 do_vert(it->fv1) 00098 do_vert(it->fv2) 00099 do_vert(it->fv3) 00100 #undef do_vert 00101 } 00102 float * pointer_offset = 0; 00103 #ifdef USE_VERTEX_BUFFER_OBJECTS 00104 if (GLEW_ARB_vertex_buffer_object) 00105 { 00106 // use a vertex buffer object if supported. 00107 glGenBuffersARB(1, &buffer_name); 00108 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer_name); 00109 glBufferDataARB(GL_ARRAY_BUFFER_ARB, 00110 sizeof(GLfloat) * data.size(), 00111 &(data[0]), 00112 GL_STATIC_DRAW_ARB); 00113 } else { 00114 #endif 00115 // Use vertex arrays. 00116 pointer_offset = &(data[0]); 00117 00118 #ifdef USE_VERTEX_BUFFER_OBJECTS 00119 } 00120 #endif 00121 glEnableClientState(GL_NORMAL_ARRAY); 00122 glNormalPointer(GL_FLOAT, 8 * sizeof(GLfloat), pointer_offset); 00123 00124 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 00125 glTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), pointer_offset + 3); 00126 00127 glEnableClientState(GL_VERTEX_ARRAY); 00128 glVertexPointer(3, GL_FLOAT, 8 * sizeof(GLfloat), pointer_offset + 5); 00129 00130 display_list = glGenLists(1); 00131 glNewList(display_list, GL_COMPILE); 00132 switch (render_mode) 00133 { 00134 case RM_SOLID: 00135 glDrawArrays(GL_TRIANGLES, 0, faces.size() * 3); 00136 break; 00137 case RM_WIREFRAME: 00138 for (unsigned int i = 0; i < faces.size(); i++) 00139 { 00140 glDrawArrays(GL_LINE_LOOP, i * 3, 3); 00141 } 00142 break; 00143 } 00144 glEndList(); 00145 00146 glDisableClientState(GL_NORMAL_ARRAY); 00147 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 00148 glDisableClientState(GL_VERTEX_ARRAY); 00149 00150 #ifdef USE_VERTEX_BUFFER_OBJECTS 00151 if (GLEW_ARB_vertex_buffer_object) 00152 { 00153 glDeleteBuffersARB(1, &buffer_name); 00154 } 00155 #endif 00156 00157 return &display_list; 00158 } 00159 00160 void DrawableMesh::delete_list(unsigned int * display_list) 00161 { 00162 glDeleteLists(*display_list, 1); 00163 } 00164 00165 void DrawableMesh::set_render_mode(RenderMode new_render_mode) 00166 { 00167 if (new_render_mode == render_mode) return; 00168 render_mode = new_render_mode; 00169 // this cleans up the display list if there was one already. 00170 list_handle = boost::shared_ptr<unsigned int>(); 00171 } 00172 00173 }
Generated at Mon Sep 6 00:41:11 2010 by Doxygen version 1.4.7 for Racer version svn335.