Ghost Context Refactor
[blender-staging.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_StorageVBO.cpp
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 "glew-mx.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 = sizeof(RAS_TexVert);
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 = (void*)(((RAS_TexVert*)0)->getXYZ());
58         this->normal_offset = (void*)(((RAS_TexVert*)0)->getNormal());
59         this->tangent_offset = (void*)(((RAS_TexVert*)0)->getTangent());
60         this->color_offset = (void*)(((RAS_TexVert*)0)->getRGBA());
61         this->uv_offset = (void*)(((RAS_TexVert*)0)->getUV(0));
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         glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id);
73         glBufferData(GL_ARRAY_BUFFER, this->stride*this->size, &this->data->m_vertex[0], GL_STATIC_DRAW);
74 }
75
76 void VBO::UpdateIndices()
77 {
78         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo);
79         glBufferData(GL_ELEMENT_ARRAY_BUFFER, data->m_index.size() * sizeof(GLushort),
80                                         &data->m_index[0], GL_STATIC_DRAW);
81 }
82
83 void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer, bool multi)
84 {
85         int unit;
86
87         // Bind buffers
88         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo);
89         glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id);
90
91         // Vertexes
92         glEnableClientState(GL_VERTEX_ARRAY);
93         glVertexPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
94
95         // Normals
96         glEnableClientState(GL_NORMAL_ARRAY);
97         glNormalPointer(GL_FLOAT, this->stride, this->normal_offset);
98
99         // Colors
100         glEnableClientState(GL_COLOR_ARRAY);
101         glColorPointer(4, GL_UNSIGNED_BYTE, this->stride, this->color_offset);
102
103         if (multi)
104         {
105                 for (unit = 0; unit < texco_num; ++unit)
106                 {
107                         glClientActiveTexture(GL_TEXTURE0_ARB + unit);
108                         switch (texco[unit]) {
109                                 case RAS_IRasterizer::RAS_TEXCO_ORCO:
110                                 case RAS_IRasterizer::RAS_TEXCO_GLOB:
111                                         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
112                                         glTexCoordPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
113                                         break;
114                                 case RAS_IRasterizer::RAS_TEXCO_UV:
115                                         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
116                                         glTexCoordPointer(2, GL_FLOAT, this->stride, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit)));
117                                         break;
118                                 case RAS_IRasterizer::RAS_TEXCO_NORM:
119                                         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
120                                         glTexCoordPointer(3, GL_FLOAT, this->stride, this->normal_offset);
121                                         break;
122                                 case RAS_IRasterizer::RAS_TEXTANGENT:
123                                         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
124                                         glTexCoordPointer(4, GL_FLOAT, this->stride, this->tangent_offset);
125                                         break;
126                                 default:
127                                         break;
128                         }
129                 }
130                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
131         }
132         else //TexFace
133         {
134                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
135                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
136                 glTexCoordPointer(2, GL_FLOAT, this->stride, this->uv_offset);
137         }
138
139         if (GLEW_ARB_vertex_program)
140         {
141                 for (unit = 0; unit < attrib_num; ++unit)
142                 {
143                         switch (attrib[unit]) {
144                                 case RAS_IRasterizer::RAS_TEXCO_ORCO:
145                                 case RAS_IRasterizer::RAS_TEXCO_GLOB:
146                                         glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, this->stride, this->vertex_offset);
147                                         glEnableVertexAttribArrayARB(unit);
148                                         break;
149                                 case RAS_IRasterizer::RAS_TEXCO_UV:
150                                         glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, this->stride, (void*)((intptr_t)this->uv_offset+attrib_layer[unit]*sizeof(GLfloat)*2));
151                                         glEnableVertexAttribArrayARB(unit);
152                                         break;
153                                 case RAS_IRasterizer::RAS_TEXCO_NORM:
154                                         glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, stride, this->normal_offset);
155                                         glEnableVertexAttribArrayARB(unit);
156                                         break;
157                                 case RAS_IRasterizer::RAS_TEXTANGENT:
158                                         glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, this->stride, this->tangent_offset);
159                                         glEnableVertexAttribArrayARB(unit);
160                                         break;
161                                 default:
162                                         break;
163                         }
164                 }
165         }
166         
167         glDrawElements(this->mode, this->indices, GL_UNSIGNED_SHORT, 0);
168
169         glDisableClientState(GL_VERTEX_ARRAY);
170         glDisableClientState(GL_NORMAL_ARRAY);
171         glDisableClientState(GL_COLOR_ARRAY);
172         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
173
174         if (GLEW_ARB_vertex_program)
175         {
176                 for (int i = 0; i < attrib_num; ++i)
177                         glDisableVertexAttribArrayARB(i);
178         }
179
180         glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
181         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
182 }
183
184 RAS_StorageVBO::RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer):
185         m_drawingmode(RAS_IRasterizer::KX_TEXTURED),
186         m_texco_num(texco_num),
187         m_attrib_num(attrib_num),
188         m_texco(texco),
189         m_attrib(attrib),
190         m_attrib_layer(attrib_layer)
191 {
192 }
193
194 RAS_StorageVBO::~RAS_StorageVBO()
195 {
196 }
197
198 bool RAS_StorageVBO::Init()
199 {
200         return true;
201 }
202
203 void RAS_StorageVBO::Exit()
204 {
205         m_vbo_lookup.clear();
206 }
207
208 void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms)
209 {
210         IndexPrimitivesInternal(ms, false);
211 }
212
213 void RAS_StorageVBO::IndexPrimitivesMulti(RAS_MeshSlot& ms)
214 {
215         IndexPrimitivesInternal(ms, true);
216 }
217
218 void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
219 {
220         RAS_MeshSlot::iterator it;
221         VBO *vbo;
222
223         for (ms.begin(it); !ms.end(it); ms.next(it))
224         {
225                 vbo = m_vbo_lookup[it.array];
226
227                 if (vbo == 0)
228                         m_vbo_lookup[it.array] = vbo = new VBO(it.array, it.totindex);
229
230                 // Update the vbo
231                 if (ms.m_mesh->MeshModified())
232                 {
233                         vbo->UpdateData();
234                 }
235
236                 vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, m_attrib_layer, multi);
237         }
238 }