OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
| 3 * |
| 4 * This program is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU General Public License |
| 6 * as published by the Free Software Foundation; either version 2 |
| 7 * of the License, or (at your option) any later version. |
| 8 * |
| 9 * This program is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software Foundation, |
| 16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 17 * |
| 18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. |
| 19 * All rights reserved. |
| 20 * |
| 21 * The Original Code is: all of this file. |
| 22 * |
| 23 * Contributor(s): none yet. |
| 24 * |
| 25 * ***** END GPL LICENSE BLOCK ***** |
| 26 */ |
| 27 |
| 28 #include "RAS_StorageVBO.h" |
| 29 #include "RAS_MeshObject.h" |
| 30 |
| 31 #include "GL/glew.h" |
| 32 |
| 33 VBO::VBO(RAS_DisplayArray *data, unsigned int indices) |
| 34 { |
| 35 this->data = data; |
| 36 this->size = data->m_vertex.size(); |
| 37 this->indices = indices; |
| 38 this->stride = 32*sizeof(GLfloat); // ATI cards really like 32byte align
ed VBOs, so we add a little padding |
| 39 |
| 40 // Determine drawmode |
| 41 if (data->m_type == data->QUAD) |
| 42 this->mode = GL_QUADS; |
| 43 else if (data->m_type == data->TRIANGLE) |
| 44 this->mode = GL_TRIANGLES; |
| 45 else |
| 46 this->mode = GL_LINE; |
| 47 |
| 48 // Generate Buffers |
| 49 glGenBuffersARB(1, &this->ibo); |
| 50 glGenBuffersARB(1, &this->vbo_id); |
| 51 |
| 52 // Fill the buffers with initial data |
| 53 UpdateIndices(); |
| 54 UpdateData(); |
| 55 |
| 56 // Establish offsets |
| 57 this->vertex_offset = 0; |
| 58 this->normal_offset = (void*)(3*sizeof(GLfloat)); |
| 59 this->tangent_offset = (void*)(6*sizeof(GLfloat)); |
| 60 this->color_offset = (void*)(10*sizeof(GLfloat)); |
| 61 this->uv_offset = (void*)(11*sizeof(GLfloat)); |
| 62 } |
| 63 |
| 64 VBO::~VBO() |
| 65 { |
| 66 glDeleteBuffersARB(1, &this->ibo); |
| 67 glDeleteBuffersARB(1, &this->vbo_id); |
| 68 } |
| 69 |
| 70 void VBO::UpdateData() |
| 71 { |
| 72 unsigned int i, j, k; |
| 73 ········ |
| 74 glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id); |
| 75 glBufferData(GL_ARRAY_BUFFER, this->stride*this->size, NULL, GL_STATIC_D
RAW); |
| 76 |
| 77 // Map the buffer |
| 78 GLfloat *vbo_map = (GLfloat*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRIT
E_ONLY_ARB); |
| 79 |
| 80 // Gather data |
| 81 for (i = 0, j = 0; i < data->m_vertex.size(); i++, j += this->stride/siz
eof(GLfloat)) |
| 82 { |
| 83 memcpy(&vbo_map[j], data->m_vertex[i].getXYZ(), sizeof(float)*3)
; |
| 84 memcpy(&vbo_map[j+3], data->m_vertex[i].getNormal(), sizeof(floa
t)*3); |
| 85 memcpy(&vbo_map[j+6], data->m_vertex[i].getTangent(), sizeof(flo
at)*4); |
| 86 memcpy(&vbo_map[j+10], data->m_vertex[i].getRGBA(), sizeof(char)
*4); |
| 87 |
| 88 for (k = 0; k < RAS_TexVert::MAX_UNIT; k++) |
| 89 memcpy(&vbo_map[j+11+(k*2)], data->m_vertex[i].getUV(k),
sizeof(float)*2); |
| 90 } |
| 91 ········ |
| 92 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); |
| 93 } |
| 94 |
| 95 void VBO::UpdateIndices() |
| 96 { |
| 97 int space = data->m_index.size() * sizeof(GLushort); |
| 98 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo); |
| 99 |
| 100 // Upload Data to VBO |
| 101 glBufferData(GL_ELEMENT_ARRAY_BUFFER, space, &data->m_index[0], GL_STATI
C_DRAW); |
| 102 } |
| 103 |
| 104 void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num,
RAS_IRasterizer::TexCoGen* attrib, bool multi) |
| 105 { |
| 106 int unit; |
| 107 ········ |
| 108 // Bind buffers |
| 109 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo); |
| 110 glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id); |
| 111 |
| 112 // Vertexes |
| 113 glEnableClientState(GL_VERTEX_ARRAY); |
| 114 glVertexPointer(3, GL_FLOAT, this->stride, this->vertex_offset); |
| 115 |
| 116 // Normals |
| 117 glEnableClientState(GL_NORMAL_ARRAY); |
| 118 glNormalPointer(GL_FLOAT, this->stride, this->normal_offset); |
| 119 |
| 120 // Colors |
| 121 glEnableClientState(GL_COLOR_ARRAY); |
| 122 glColorPointer(4, GL_UNSIGNED_BYTE, this->stride, this->color_offset); |
| 123 |
| 124 if (multi) |
| 125 { |
| 126 for (unit = 0; unit < texco_num; ++unit) |
| 127 { |
| 128 glClientActiveTexture(GL_TEXTURE0_ARB + unit); |
| 129 switch (texco[unit]) { |
| 130 case RAS_IRasterizer::RAS_TEXCO_ORCO: |
| 131 case RAS_IRasterizer::RAS_TEXCO_GLOB: |
| 132 glEnableClientState(GL_TEXTURE_COORD_ARR
AY); |
| 133 glTexCoordPointer(3, GL_FLOAT, this->str
ide, this->vertex_offset); |
| 134 break; |
| 135 case RAS_IRasterizer::RAS_TEXCO_UV: |
| 136 glEnableClientState(GL_TEXTURE_COORD_ARR
AY); |
| 137 glTexCoordPointer(2, GL_FLOAT, this->str
ide, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit))); |
| 138 break; |
| 139 case RAS_IRasterizer::RAS_TEXCO_NORM: |
| 140 glEnableClientState(GL_TEXTURE_COORD_ARR
AY); |
| 141 glTexCoordPointer(3, GL_FLOAT, this->str
ide, this->normal_offset); |
| 142 break; |
| 143 case RAS_IRasterizer::RAS_TEXTANGENT: |
| 144 glEnableClientState(GL_TEXTURE_COORD_ARR
AY); |
| 145 glTexCoordPointer(4, GL_FLOAT, this->str
ide, this->tangent_offset); |
| 146 break; |
| 147 default: |
| 148 break; |
| 149 } |
| 150 } |
| 151 glClientActiveTextureARB(GL_TEXTURE0_ARB); |
| 152 } |
| 153 else //TexFace |
| 154 { |
| 155 glClientActiveTextureARB(GL_TEXTURE0_ARB); |
| 156 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
| 157 glTexCoordPointer(2, GL_FLOAT, this->stride, this->uv_offset); |
| 158 } |
| 159 |
| 160 if (GLEW_ARB_vertex_program) |
| 161 { |
| 162 int uv = 0; |
| 163 for (unit = 0; unit < attrib_num; ++unit) |
| 164 { |
| 165 switch (attrib[unit]) { |
| 166 case RAS_IRasterizer::RAS_TEXCO_ORCO: |
| 167 case RAS_IRasterizer::RAS_TEXCO_GLOB: |
| 168 glVertexAttribPointerARB(unit, 3, GL_FLO
AT, GL_FALSE, this->stride, this->vertex_offset); |
| 169 glEnableVertexAttribArrayARB(unit); |
| 170 break; |
| 171 case RAS_IRasterizer::RAS_TEXCO_UV: |
| 172 glVertexAttribPointerARB(unit, 2, GL_FLO
AT, GL_FALSE, this->stride, (void*)((intptr_t)this->uv_offset+uv)); |
| 173 uv += sizeof(GLfloat)*2; |
| 174 glEnableVertexAttribArrayARB(unit); |
| 175 break; |
| 176 case RAS_IRasterizer::RAS_TEXCO_NORM: |
| 177 glVertexAttribPointerARB(unit, 2, GL_FLO
AT, GL_FALSE, stride, this->normal_offset); |
| 178 glEnableVertexAttribArrayARB(unit); |
| 179 break; |
| 180 case RAS_IRasterizer::RAS_TEXTANGENT: |
| 181 glVertexAttribPointerARB(unit, 4, GL_FLO
AT, GL_FALSE, this->stride, this->tangent_offset); |
| 182 glEnableVertexAttribArrayARB(unit); |
| 183 break; |
| 184 default: |
| 185 break; |
| 186 } |
| 187 } |
| 188 } |
| 189 ········ |
| 190 glDrawElements(this->mode, this->indices, GL_UNSIGNED_SHORT, 0); |
| 191 |
| 192 glDisableClientState(GL_VERTEX_ARRAY); |
| 193 glDisableClientState(GL_NORMAL_ARRAY); |
| 194 glDisableClientState(GL_COLOR_ARRAY); |
| 195 glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
| 196 |
| 197 if (GLEW_ARB_vertex_program) |
| 198 { |
| 199 for (int i = 0; i < attrib_num; ++i) |
| 200 glDisableVertexAttribArrayARB(i); |
| 201 } |
| 202 |
| 203 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); |
| 204 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); |
| 205 } |
| 206 |
| 207 RAS_StorageVBO::RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco,
int *attrib_num, RAS_IRasterizer::TexCoGen *attrib): |
| 208 m_texco_num(texco_num), |
| 209 m_texco(texco), |
| 210 m_attrib_num(attrib_num), |
| 211 m_attrib(attrib) |
| 212 { |
| 213 } |
| 214 |
| 215 RAS_StorageVBO::~RAS_StorageVBO() |
| 216 { |
| 217 } |
| 218 |
| 219 bool RAS_StorageVBO::Init() |
| 220 { |
| 221 return true; |
| 222 } |
| 223 |
| 224 void RAS_StorageVBO::Exit() |
| 225 { |
| 226 m_vbo_lookup.clear(); |
| 227 } |
| 228 |
| 229 void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms) |
| 230 { |
| 231 IndexPrimitivesInternal(ms, false); |
| 232 } |
| 233 |
| 234 void RAS_StorageVBO::IndexPrimitivesMulti(RAS_MeshSlot& ms) |
| 235 { |
| 236 IndexPrimitivesInternal(ms, true); |
| 237 } |
| 238 |
| 239 void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) |
| 240 { |
| 241 RAS_MeshSlot::iterator it; |
| 242 VBO *vbo; |
| 243 ········ |
| 244 for (ms.begin(it); !ms.end(it); ms.next(it)) |
| 245 { |
| 246 vbo = m_vbo_lookup[it.array]; |
| 247 |
| 248 if (vbo == 0) |
| 249 m_vbo_lookup[it.array] = vbo = new VBO(it.array, it.toti
ndex); |
| 250 |
| 251 // Update the vbo |
| 252 if (ms.m_mesh->MeshModified()) |
| 253 { |
| 254 vbo->UpdateData(); |
| 255 } |
| 256 |
| 257 vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, multi)
; |
| 258 } |
| 259 } |
OLD | NEW |