buffer.cpp

Go to the documentation of this file.
00001 /*
00002     RenderStack  Support library for OpenGL 3+
00003     Copyright (C) 2010  Timo Suoranta
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Lesser General Public
00007     License as published by the Free Software Foundation; either
00008     version 2.1 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Lesser General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public
00016     License along with this library; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00027 #include "renderstack/rs_gl.h"
00028 #include "renderstack/rs_log.h"
00029 #include "renderstack/buffer.hpp"
00030 #include "renderstack/vec2.hpp"
00031 #include "renderstack/vec3.hpp"
00032 #include "renderstack/vec4.hpp"
00033 
00034 namespace renderstack {
00035 
00036 
00037 buffer::buffer(
00038     int gl_target, 
00039     int gl_usage
00040 )
00041 :   m_gl_buffer_object  ((unsigned int)(~0))
00042 ,   m_gl_target         (gl_target)
00043 ,   m_gl_usage          (gl_usage)
00044 {
00045     ::rs_gl_gen_buffers(1, &m_gl_buffer_object);
00046 }
00047 
00048 buffer::buffer(
00049     int gl_target, 
00050     int gl_usage, 
00051     int gl_index_type, 
00052     int gl_mode
00053 )
00054 :   m_gl_buffer_object  ((unsigned int)(~0))
00055 ,   m_gl_target         (gl_target)
00056 ,   m_gl_usage          (gl_usage)
00057 ,   m_gl_index_type     (gl_index_type)
00058 ,   m_gl_mode           (gl_mode)
00059 {
00060     ::rs_gl_gen_buffers(1, &m_gl_buffer_object);
00061 }
00062 
00063 buffer::~buffer()
00064 {
00065     ::GLboolean is_buffer = ::rs_gl_is_buffer(m_gl_buffer_object);
00066     if(is_buffer != GL_FALSE)
00067     {
00068         ::rs_gl_delete_buffers(1, &m_gl_buffer_object);
00069     }
00070     else
00071     {
00072         ::rs_log("glIsBuffer() == GL_FALSE\n");
00073     }
00074 }
00075 
00076 void buffer::begin_edit()
00077 {
00078     if(m_gl_target == GL_ARRAY_BUFFER)
00079     {
00080         m_stride = vertex_format().stride();
00081     }
00082     else if(m_gl_target == GL_ELEMENT_ARRAY_BUFFER)
00083     {
00084         m_stride = gl_size_of_type(gl_index_type());
00085     }
00086     else
00087     {
00088         throw invalid_buffer_gl_target_exception(m_gl_target);
00089     }
00090 
00091     if(m_stride == 0)
00092     {
00093         throw invalid_buffer_stride_exception();
00094     }
00095 
00096     m_current_index = 0;
00097 }
00098 
00099 void buffer::end_edit(uint32 end_index)
00100 {
00101     uint32 current_size = end_index * m_stride;
00102 
00103     if(current_size == 0)
00104     {
00105         return;
00106     }
00107 
00108     m_count = end_index;
00109     m_size  = current_size;
00110 
00111     ::rs_gl_bind_buffer(
00112         gl_target(), 
00113         gl_buffer_object()
00114     );
00115 
00116     ::rs_gl_buffer_data(
00117         gl_target(),   /*  gl target       */ 
00118         current_size,  /*  length          */ 
00119         &m_data[0],    /*  data pointer    */ 
00120         gl_usage()     /*  gl usage        */ 
00121     );
00122 
00123     /*  This will free the memory  */ 
00124     std::vector<unsigned char> dummy;
00125     m_data = dummy;
00126 }
00127 
00128 void buffer::use() const
00129 {
00130     ::rs_gl_bind_buffer(
00131         gl_target(),
00132         gl_buffer_object()
00133     );
00134 }
00135 
00136 
00137 void buffer::set_index(uint32 index)
00138 {
00139     m_current_index = index;
00140 
00141     size_t offset = m_current_index * m_stride;
00142 
00143     /*  writing for example triangle writes 2 indices past current index  */ 
00144     if(offset + (4 * m_stride) > m_data.size())
00145     {
00146         size_t adjusted_capacity = m_data.size();
00147 
00148         /*  start with initial 32 kB  */ 
00149         if(adjusted_capacity == 0)
00150         {
00151             adjusted_capacity = 32 * 1024;
00152         }
00153 
00154         while(offset + (4 * m_stride) > adjusted_capacity)
00155         {
00156             adjusted_capacity *= 2;
00157         }
00158         if(adjusted_capacity != m_data.size())
00159         {
00160             m_data.resize(adjusted_capacity);
00161         }
00162     }
00163 }
00164 
00165 void buffer::put_float(vertex_attribute const &attribute, float x)
00166 {
00167     size_t  offset   = m_current_index * m_stride + attribute.offset();
00168     float   *pointer = reinterpret_cast<float*>(&m_data[offset]);
00169 
00170     pointer[0] = x;
00171 }
00172 
00173 void buffer::put_vec2(vertex_attribute const &attribute, vec2 const &v)
00174 {
00175     size_t  offset   = m_current_index * m_stride + attribute.offset();
00176     float   *pointer = reinterpret_cast<float*>(&m_data[offset]);
00177 
00178     pointer[0] = v.x;
00179     pointer[1] = v.y;
00180 }
00181 
00182 void buffer::put_vec2(vertex_attribute const &attribute, float x, float y)
00183 {
00184     size_t  offset   = m_current_index * m_stride + attribute.offset();
00185     float   *pointer = reinterpret_cast<float*>(&m_data[offset]);
00186 
00187     pointer[0] = x;
00188     pointer[1] = y;
00189 }
00190 
00191 void buffer::put_vec3(vertex_attribute const &attribute, vec3 const &v)
00192 {
00193     size_t  offset   = m_current_index * m_stride + attribute.offset();
00194     float   *pointer = reinterpret_cast<float*>(&m_data[offset]);
00195 
00196     pointer[0] = v.x;
00197     pointer[1] = v.y;
00198     pointer[2] = v.z;
00199 }
00200 
00201 void buffer::put_vec3(vertex_attribute const &attribute, float x, float y, float z)
00202 {
00203     size_t  offset   = m_current_index * m_stride + attribute.offset();
00204     float   *pointer = reinterpret_cast<float*>(&m_data[offset]);
00205 
00206     pointer[0] = x;
00207     pointer[1] = y;
00208     pointer[2] = z;
00209 }
00210 
00211 void buffer::put_vec4(vertex_attribute const &attribute, vec4 const &v)
00212 {
00213     size_t  offset   = m_current_index * m_stride + attribute.offset();
00214     float   *pointer = reinterpret_cast<float*>(&m_data[offset]);
00215 
00216     pointer[0] = v.x;
00217     pointer[1] = v.y;
00218     pointer[2] = v.z;
00219     pointer[3] = v.w;
00220 }
00221 
00222 void buffer::put_vec4(vertex_attribute const &attribute, float x, float y, float z, float w)
00223 {
00224     size_t  offset   = m_current_index * m_stride + attribute.offset();
00225     float   *pointer = reinterpret_cast<float*>(&m_data[offset]);
00226 
00227     pointer[0] = x;
00228     pointer[1] = y;
00229     pointer[2] = z;
00230     pointer[3] = w;
00231 }
00232 
00233 void buffer::put_uint16(vertex_attribute const &attribute, uint16 x)
00234 {
00235     size_t  offset   = m_current_index * m_stride + attribute.offset();
00236     uint16  *pointer = reinterpret_cast<uint16*>(&m_data[offset]);
00237 
00238     pointer[0] = x;
00239 }
00240 
00241 void buffer::put_uint32(vertex_attribute const &attribute, uint32 x)
00242 {
00243     size_t  offset   = m_current_index * m_stride + attribute.offset();
00244     uint32  *pointer = reinterpret_cast<uint32*>(&m_data[offset]);
00245 
00246     pointer[0] = x;
00247 }
00248 
00249 void buffer::put_position(vec3 const &v, int index)
00250 {
00251     vertex_attribute const &attribute = vertex_format().attribute(
00252         vertex_attribute_usage_position,
00253         index
00254     );
00255 
00256     put_vec3(attribute, v);
00257 }
00258 
00259 void buffer::put_position(float x, float y, float z, int index)
00260 {
00261     vertex_attribute const &attribute = vertex_format().attribute(
00262         vertex_attribute_usage_position,
00263         index
00264     );
00265 
00266     put_vec3(attribute, x, y, z);
00267 }
00268 
00269 void buffer::put_normal(vec3 const &v, int index)
00270 {
00271     vertex_attribute const &attribute = vertex_format().attribute(
00272         vertex_attribute_usage_normal,
00273         index
00274     );
00275 
00276     put_vec3(attribute, v);
00277 }
00278 
00279 void buffer::put_normal(float x, float y, float z, int index)
00280 {
00281     vertex_attribute const &attribute = vertex_format().attribute(
00282         vertex_attribute_usage_normal,
00283         index
00284     );
00285 
00286     put_vec3(attribute, x, y, z);
00287 }
00288 
00289 void buffer::put_texcoord(vec2 const &v, int index)
00290 {
00291     vertex_attribute const &attribute = vertex_format().attribute(
00292         vertex_attribute_usage_texcoord,
00293         index
00294     );
00295 
00296     put_vec2(attribute, v);
00297 }
00298 
00299 void buffer::put_texcoord(float s, float t, int index)
00300 {
00301     vertex_attribute const &attribute = vertex_format().attribute(
00302         vertex_attribute_usage_texcoord,
00303         index
00304     );
00305 
00306     put_vec2(attribute, s, t);
00307 }
00308 
00309 void buffer::put_index(uint32 index_location, uint32 index_value)
00310 {
00311     switch(m_stride)
00312     {
00313         case 1:
00314         {
00315             size_t    offset   = index_location * m_stride;
00316             ::GLubyte *pointer = reinterpret_cast<::GLubyte*>(&m_data[offset]);
00317 
00318             if(
00319                 (index_value > 0xff) 
00320             )
00321             {
00322                 throw index_out_of_range_exception();
00323             }
00324 
00325             pointer[0] = static_cast<::GLubyte>(index_value & 0xff);
00326 
00327             break;
00328         }
00329         case 2:
00330         {
00331             size_t     offset   = index_location * m_stride;
00332             ::GLushort *pointer = reinterpret_cast<::GLushort*>(&m_data[offset]);
00333 
00334             if(
00335                 (index_value > 0xffff) 
00336             )
00337             {
00338                 throw index_out_of_range_exception();
00339             }
00340 
00341             pointer[0] = static_cast<::GLushort>(index_value & 0xffff);
00342 
00343             break;
00344         }
00345         case 4:
00346         {
00347             size_t   offset   = index_location * m_stride;
00348             ::GLuint *pointer = reinterpret_cast<::GLuint*>(&m_data[offset]);
00349 
00350             pointer[0] = index_value;
00351 
00352             break;
00353         }
00354         default:
00355         {
00356             throw invalid_buffer_stride_exception();
00357         }
00358     }
00359 }
00360 
00361 void buffer::point(uint32 index0)
00362 {
00363     put_index(m_current_index, index0);
00364 }
00365 
00366 void buffer::line(uint32 index0, uint32 index1)
00367 {
00368     put_index(m_current_index    , index0);
00369     put_index(m_current_index + 1, index1);
00370 }
00371 
00372 void buffer::triangle(uint32 index0, uint32 index1, uint32 index2)
00373 {
00374     put_index(m_current_index    , index0);
00375     put_index(m_current_index + 1, index1);
00376     put_index(m_current_index + 2, index2);
00377 }
00378 
00379 void buffer::quad(uint32 index0, uint32 index1, uint32 index2, uint32 index3)
00380 {
00381     put_index(m_current_index    , index0);
00382     put_index(m_current_index + 1, index1);
00383     put_index(m_current_index + 2, index2);
00384     put_index(m_current_index + 3, index0);
00385     put_index(m_current_index + 4, index2);
00386     put_index(m_current_index + 5, index3);
00387 }
00388 
00389 }
00390 
Generated on Sun Apr 11 12:23:08 2010 for RenderStack by  doxygen 1.6.3