code cleanup: bge builds with clang without warnings / errors.
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_VAOpenGLRasterizer.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 /** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
29  *  \ingroup bgerastogl
30  */
31
32 #include "RAS_VAOpenGLRasterizer.h"
33 #include <stdlib.h>
34
35 #include "GL/glew.h"
36 #include "GPU_extensions.h"
37
38 #include "STR_String.h"
39 #include "RAS_TexVert.h"
40 #include "MT_CmMatrix4x4.h"
41 #include "RAS_IRenderTools.h" // rendering text
42         
43 RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock)
44 :       RAS_OpenGLRasterizer(canvas),
45         /* m_Lock(lock && GLEW_EXT_compiled_vertex_array), */ /* UNUSED */
46         m_last_texco_num(0),
47         m_last_attrib_num(0)
48 {
49 }
50
51 RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
52 {
53 }
54
55 bool RAS_VAOpenGLRasterizer::Init(void)
56 {
57         
58         bool result = RAS_OpenGLRasterizer::Init();
59         
60         if (result)
61         {
62                 glEnableClientState(GL_VERTEX_ARRAY);
63                 glEnableClientState(GL_NORMAL_ARRAY);
64                 glDisableClientState(GL_COLOR_ARRAY);
65                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
66
67                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
68         }
69
70         return result;
71 }
72
73 void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
74 {
75         m_drawingmode = drawingmode;
76
77         switch (m_drawingmode)
78         {
79                 case KX_BOUNDINGBOX:
80                 case KX_WIREFRAME:
81                         //glDisableClientState(GL_COLOR_ARRAY);
82                         //glDisable(GL_CULL_FACE);
83                         break;
84                 case KX_SOLID:
85                         //glDisableClientState(GL_COLOR_ARRAY);
86                         break;
87                 case KX_TEXTURED:
88                 case KX_SHADED:
89                 case KX_SHADOW:
90                         //glEnableClientState(GL_COLOR_ARRAY);
91                 default:
92                         break;
93         }
94 }
95
96 void RAS_VAOpenGLRasterizer::Exit()
97 {
98         glDisableClientState(GL_VERTEX_ARRAY);
99         glDisableClientState(GL_NORMAL_ARRAY);
100         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
101         glDisableClientState(GL_COLOR_ARRAY);
102
103         RAS_OpenGLRasterizer::Exit();
104 }
105
106 void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
107 {
108         static const GLsizei stride = sizeof(RAS_TexVert);
109         bool wireframe = m_drawingmode <= KX_WIREFRAME;
110         RAS_MeshSlot::iterator it;
111         GLenum drawmode;
112
113         if (ms.m_pDerivedMesh) {
114                 // cannot be handled here, pass to RAS_OpenGLRasterizer
115                 RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false);
116                 return;
117         }
118
119         if (!wireframe)
120                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
121
122         // use glDrawElements to draw each vertexarray
123         for (ms.begin(it); !ms.end(it); ms.next(it)) {
124                 if (it.totindex == 0)
125                         continue;
126
127                 // drawing mode
128                 if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
129                         drawmode = GL_TRIANGLES;
130                 else if (it.array->m_type == RAS_DisplayArray::QUAD)
131                         drawmode = GL_QUADS;
132                 else
133                         drawmode = GL_LINES;
134
135                 // colors
136                 if (drawmode != GL_LINES && !wireframe) {
137                         if (ms.m_bObjectColor) {
138                                 const MT_Vector4& rgba = ms.m_RGBAcolor;
139
140                                 glDisableClientState(GL_COLOR_ARRAY);
141                                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
142                         }
143                         else {
144                                 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
145                                 glEnableClientState(GL_COLOR_ARRAY);
146                         }
147                 }
148                 else
149                         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
150
151                 glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
152                 glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
153                 if (!wireframe) {
154                         glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1());
155                         if (glIsEnabled(GL_COLOR_ARRAY))
156                                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
157                 }
158
159                 // here the actual drawing takes places
160                 glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
161         }
162
163         if (!wireframe) {
164                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
165                 glDisableClientState(GL_COLOR_ARRAY);
166         }
167 }
168
169 void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
170 {
171         static const GLsizei stride = sizeof(RAS_TexVert);
172         bool wireframe = m_drawingmode <= KX_WIREFRAME;
173         RAS_MeshSlot::iterator it;
174         GLenum drawmode;
175
176         if (ms.m_pDerivedMesh) {
177                 // cannot be handled here, pass to RAS_OpenGLRasterizer
178                 RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true);
179                 return;
180         }
181
182         if (!wireframe)
183                 EnableTextures(true);
184
185         // use glDrawElements to draw each vertexarray
186         for (ms.begin(it); !ms.end(it); ms.next(it)) {
187                 if (it.totindex == 0)
188                         continue;
189
190                 // drawing mode
191                 if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
192                         drawmode = GL_TRIANGLES;
193                 else if (it.array->m_type == RAS_DisplayArray::QUAD)
194                         drawmode = GL_QUADS;
195                 else
196                         drawmode = GL_LINES;
197
198                 // colors
199                 if (drawmode != GL_LINES && !wireframe) {
200                         if (ms.m_bObjectColor) {
201                                 const MT_Vector4& rgba = ms.m_RGBAcolor;
202
203                                 glDisableClientState(GL_COLOR_ARRAY);
204                                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
205                         }
206                         else {
207                                 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
208                                 glEnableClientState(GL_COLOR_ARRAY);
209                         }
210                 }
211                 else
212                         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
213
214                 glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
215                 glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
216                 if (!wireframe) {
217                         TexCoordPtr(it.vertex);
218                         if (glIsEnabled(GL_COLOR_ARRAY))
219                                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
220                 }
221
222                 // here the actual drawing takes places
223                 glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
224         }
225
226         if (!wireframe) {
227                 glDisableClientState(GL_COLOR_ARRAY);
228                 EnableTextures(false);
229         }
230 }
231
232 void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
233 {
234         /* note: this function must closely match EnableTextures to enable/disable
235          * the right arrays, otherwise coordinate and attribute pointers from other
236          * materials can still be used and cause crashes */
237         int unit;
238
239         if (GLEW_ARB_multitexture)
240         {
241                 for (unit=0; unit<m_texco_num; unit++)
242                 {
243                         glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
244                         if (tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) {
245                                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
246                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
247                                 continue;
248                         }
249                         switch(m_texco[unit])
250                         {
251                         case RAS_TEXCO_ORCO:
252                         case RAS_TEXCO_GLOB:
253                                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ());
254                                 break;
255                         case RAS_TEXCO_UV1:
256                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
257                                 break;
258                         case RAS_TEXCO_NORM:
259                                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
260                                 break;
261                         case RAS_TEXTANGENT:
262                                 glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
263                                 break;
264                         case RAS_TEXCO_UV2:
265                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2());
266                                 break;
267                         default:
268                                 break;
269                         }
270                 }
271
272                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
273         }
274
275         if (GLEW_ARB_vertex_program) {
276                 for (unit=0; unit<m_attrib_num; unit++) {
277                         switch(m_attrib[unit]) {
278                         case RAS_TEXCO_ORCO:
279                         case RAS_TEXCO_GLOB:
280                                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ());
281                                 break;
282                         case RAS_TEXCO_UV1:
283                                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1());
284                                 break;
285                         case RAS_TEXCO_NORM:
286                                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal());
287                                 break;
288                         case RAS_TEXTANGENT:
289                                 glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent());
290                                 break;
291                         case RAS_TEXCO_UV2:
292                                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2());
293                                 break;
294                         case RAS_TEXCO_VCOL:
295                                 glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA());
296                                 break;
297                         default:
298                                 break;
299                         }
300                 }
301         }
302 }
303
304 void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
305 {
306         TexCoGen *texco, *attrib;
307         int unit, texco_num, attrib_num;
308
309         /* we cache last texcoords and attribs to ensure we disable the ones that
310          * were actually last set */
311         if (enable) {
312                 texco = m_texco;
313                 texco_num = m_texco_num;
314                 attrib = m_attrib;
315                 attrib_num = m_attrib_num;
316                 
317                 memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num);
318                 m_last_texco_num = m_texco_num;
319                 memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num);
320                 m_last_attrib_num = m_attrib_num;
321         }
322         else {
323                 texco = m_last_texco;
324                 texco_num = m_last_texco_num;
325                 attrib = m_last_attrib;
326                 attrib_num = m_last_attrib_num;
327         }
328
329         if (GLEW_ARB_multitexture) {
330                 for (unit=0; unit<texco_num; unit++) {
331                         glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
332
333                         switch(texco[unit])
334                         {
335                         case RAS_TEXCO_ORCO:
336                         case RAS_TEXCO_GLOB:
337                         case RAS_TEXCO_UV1:
338                         case RAS_TEXCO_NORM:
339                         case RAS_TEXTANGENT:
340                         case RAS_TEXCO_UV2:
341                                 if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
342                                 else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
343                                 break;
344                         default:
345                                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
346                                 break;
347                         }
348                 }
349
350                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
351         }
352         else {
353                 if (texco_num) {
354                         if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
355                         else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
356                 }
357         }
358
359         if (GLEW_ARB_vertex_program) {
360                 for (unit=0; unit<attrib_num; unit++) {
361                         switch(attrib[unit]) {
362                         case RAS_TEXCO_ORCO:
363                         case RAS_TEXCO_GLOB:
364                         case RAS_TEXCO_UV1:
365                         case RAS_TEXCO_NORM:
366                         case RAS_TEXTANGENT:
367                         case RAS_TEXCO_UV2:
368                         case RAS_TEXCO_VCOL:
369                                 if (enable) glEnableVertexAttribArrayARB(unit);
370                                 else glDisableVertexAttribArrayARB(unit);
371                                 break;
372                         default:
373                                 glDisableVertexAttribArrayARB(unit);
374                                 break;
375                         }
376                 }
377         }
378
379         if (!enable) {
380                 m_last_texco_num = 0;
381                 m_last_attrib_num = 0;
382         }
383 }
384