Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_VAOpenGLRasterizer.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include "RAS_VAOpenGLRasterizer.h"
33 #include <stdlib.h>
34
35 #include "GL/glew.h"
36
37 #include "STR_String.h"
38 #include "RAS_TexVert.h"
39 #include "MT_CmMatrix4x4.h"
40 #include "RAS_IRenderTools.h" // rendering text
41         
42 RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock)
43 :       RAS_OpenGLRasterizer(canvas),
44         m_Lock(lock && GLEW_EXT_compiled_vertex_array),
45         m_last_texco_num(0),
46         m_last_attrib_num(0)
47 {
48 }
49
50 RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
51 {
52 }
53
54 bool RAS_VAOpenGLRasterizer::Init(void)
55 {
56         
57         bool result = RAS_OpenGLRasterizer::Init();
58         
59         if (result)
60         {
61                 glEnableClientState(GL_VERTEX_ARRAY);
62                 glEnableClientState(GL_NORMAL_ARRAY);
63                 glDisableClientState(GL_COLOR_ARRAY);
64                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
65
66                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
67         }
68
69         return result;
70 }
71
72 void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
73 {
74         m_drawingmode = drawingmode;
75
76         switch (m_drawingmode)
77         {
78                 case KX_BOUNDINGBOX:
79                 case KX_WIREFRAME:
80                         glDisableClientState(GL_COLOR_ARRAY);
81                         glDisable(GL_CULL_FACE);
82                         break;
83                 case KX_SOLID:
84                         glDisableClientState(GL_COLOR_ARRAY);
85                         break;
86                 case KX_TEXTURED:
87                 case KX_SHADED:
88                 case KX_SHADOW:
89                         glEnableClientState(GL_COLOR_ARRAY);
90                 default:
91                         break;
92         }
93 }
94
95 void RAS_VAOpenGLRasterizer::Exit()
96 {
97         glEnableClientState(GL_VERTEX_ARRAY);
98         glEnableClientState(GL_NORMAL_ARRAY);
99         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
100         glDisableClientState(GL_COLOR_ARRAY);
101         EnableTextures(false);
102
103         RAS_OpenGLRasterizer::Exit();
104 }
105
106 void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays,
107                                                         const vecIndexArrays & indexarrays,
108                                                         DrawMode mode,
109                                                         bool useObjectColor,
110                                                         const MT_Vector4& rgbacolor,
111                                                         class KX_ListSlot** slot)
112 {
113         static const GLsizei vtxstride = sizeof(RAS_TexVert);
114         GLenum drawmode;
115         if(mode == KX_MODE_TRIANGLES)
116                 drawmode = GL_TRIANGLES;
117         else if(mode == KX_MODE_QUADS)
118                 drawmode = GL_QUADS;
119         else
120                 drawmode = GL_LINES;
121
122         const RAS_TexVert* vertexarray;
123         unsigned int numindices, vt;
124
125         if (drawmode != GL_LINES)
126         {
127                 if (useObjectColor)
128                 {
129                         glDisableClientState(GL_COLOR_ARRAY);
130                         glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
131                 } else
132                 {
133                         glColor4d(0,0,0,1.0);
134                         glEnableClientState(GL_COLOR_ARRAY);
135                 }
136         }
137         else
138         {
139                 glColor3d(0,0,0);
140         }
141
142         EnableTextures(false);
143         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
144
145         // use glDrawElements to draw each vertexarray
146         for (vt=0;vt<vertexarrays.size();vt++)
147         {
148                 vertexarray = &((*vertexarrays[vt]) [0]);
149                 const KX_IndexArray & indexarray = (*indexarrays[vt]);
150                 numindices = indexarray.size();
151
152                 if (!numindices)
153                         continue;
154                 
155                 glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
156                 glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
157                 glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1());
158                 if(glIsEnabled(GL_COLOR_ARRAY))
159                         glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
160
161                 //if(m_Lock)
162                 //      local->Begin(vertexarrays[vt]->size());
163
164                 // here the actual drawing takes places
165                 glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0]));
166
167                 //if(m_Lock)
168                 //      local->End();
169         }
170
171         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
172 }
173
174 void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays,
175                                                         const vecIndexArrays & indexarrays,
176                                                         DrawMode mode,
177                                                         bool useObjectColor,
178                                                         const MT_Vector4& rgbacolor,
179                                                         class KX_ListSlot** slot)
180 {
181         static const GLsizei vtxstride = sizeof(RAS_TexVert);
182
183         GLenum drawmode;
184         if(mode == KX_MODE_TRIANGLES)
185                 drawmode = GL_TRIANGLES;
186         else if(mode == KX_MODE_QUADS)
187                 drawmode = GL_QUADS;
188         else
189                 drawmode = GL_LINES;
190
191         const RAS_TexVert* vertexarray;
192         unsigned int numindices, vt;
193
194         if (drawmode != GL_LINES)
195         {
196                 if (useObjectColor)
197                 {
198                         glDisableClientState(GL_COLOR_ARRAY);
199                         glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
200                 }
201                 else
202                 {
203                         glColor4d(0,0,0,1.0);
204                         glEnableClientState(GL_COLOR_ARRAY);
205                 }
206         }
207         else
208         {
209                 glColor3d(0,0,0);
210         }
211
212         // use glDrawElements to draw each vertexarray
213         for (vt=0;vt<vertexarrays.size();vt++)
214         {
215                 vertexarray = &((*vertexarrays[vt]) [0]);
216                 const KX_IndexArray & indexarray = (*indexarrays[vt]);
217                 numindices = indexarray.size();
218
219                 if (!numindices)
220                         continue;
221
222                 glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
223                 glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
224                 TexCoordPtr(vertexarray);
225                 if(glIsEnabled(GL_COLOR_ARRAY))
226                         glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
227
228                 //if(m_Lock)
229                 //      local->Begin(vertexarrays[vt]->size());
230
231                 // here the actual drawing takes places
232                 glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0]));
233                 
234                 //if(m_Lock)
235                 //      local->End();
236         }
237 }
238
239 void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
240 {
241         /* note: this function must closely match EnableTextures to enable/disable
242          * the right arrays, otherwise coordinate and attribute pointers from other
243          * materials can still be used and cause crashes */
244         int unit;
245
246         if(GLEW_ARB_multitexture)
247         {
248                 for(unit=0; unit<m_texco_num; unit++)
249                 {
250                         glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
251                         if(tv->getFlag() & TV_2NDUV && (int)tv->getUnit() == unit) {
252                                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
253                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
254                                 continue;
255                         }
256                         switch(m_texco[unit])
257                         {
258                         case RAS_TEXCO_ORCO:
259                         case RAS_TEXCO_GLOB:
260                                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getLocalXYZ());
261                                 break;
262                         case RAS_TEXCO_UV1:
263                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
264                                 break;
265                         case RAS_TEXCO_NORM:
266                                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
267                                 break;
268                         case RAS_TEXTANGENT:
269                                 glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
270                                 break;
271                         case RAS_TEXCO_UV2:
272                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2());
273                                 break;
274                         default:
275                                 break;
276                         }
277                 }
278
279                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
280         }
281
282         if(GLEW_ARB_vertex_program) {
283                 for(unit=0; unit<m_attrib_num; unit++) {
284                         switch(m_attrib[unit]) {
285                         case RAS_TEXCO_ORCO:
286                         case RAS_TEXCO_GLOB:
287                                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ());
288                                 break;
289                         case RAS_TEXCO_UV1:
290                                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1());
291                                 break;
292                         case RAS_TEXCO_NORM:
293                                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal());
294                                 break;
295                         case RAS_TEXTANGENT:
296                                 glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent());
297                                 break;
298                         case RAS_TEXCO_UV2:
299                                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2());
300                                 break;
301                         case RAS_TEXCO_VCOL:
302                                 glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA());
303                                 break;
304                         default:
305                                 break;
306                         }
307                 }
308         }
309 }
310
311 void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
312 {
313         TexCoGen *texco, *attrib;
314         int unit, texco_num, attrib_num;
315
316         /* disable previously enabled texture coordinates and attributes. ideally
317          * this shouldn't be necessary .. */
318         if(enable)
319                 EnableTextures(false);
320
321         /* we cache last texcoords and attribs to ensure we disable the ones that
322          * were actually last set */
323         if(enable) {
324                 texco = m_texco;
325                 texco_num = m_texco_num;
326                 attrib = m_attrib;
327                 attrib_num = m_attrib_num;
328                 
329                 memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num);
330                 m_last_texco_num = m_texco_num;
331                 memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num);
332                 m_last_attrib_num = m_attrib_num;
333         }
334         else {
335                 texco = m_last_texco;
336                 texco_num = m_last_texco_num;
337                 attrib = m_last_attrib;
338                 attrib_num = m_last_attrib_num;
339         }
340
341         if(GLEW_ARB_multitexture) {
342                 for(unit=0; unit<texco_num; unit++) {
343                         glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
344
345                         switch(texco[unit])
346                         {
347                         case RAS_TEXCO_ORCO:
348                         case RAS_TEXCO_GLOB:
349                         case RAS_TEXCO_UV1:
350                         case RAS_TEXCO_NORM:
351                         case RAS_TEXTANGENT:
352                         case RAS_TEXCO_UV2:
353                                 if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
354                                 else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
355                                 break;
356                         default:
357                                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
358                                 break;
359                         }
360                 }
361
362                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
363         }
364         else {
365                 if(texco_num) {
366                         if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
367                         else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
368                 }
369         }
370
371         if(GLEW_ARB_vertex_program) {
372                 for(unit=0; unit<attrib_num; unit++) {
373                         switch(attrib[unit]) {
374                         case RAS_TEXCO_ORCO:
375                         case RAS_TEXCO_GLOB:
376                         case RAS_TEXCO_UV1:
377                         case RAS_TEXCO_NORM:
378                         case RAS_TEXTANGENT:
379                         case RAS_TEXCO_UV2:
380                         case RAS_TEXCO_VCOL:
381                                 if(enable) glEnableVertexAttribArrayARB(unit);
382                                 else glDisableVertexAttribArrayARB(unit);
383                                 break;
384                         default:
385                                 glDisableVertexAttribArrayARB(unit);
386                                 break;
387                         }
388                 }
389         }
390
391         if(!enable) {
392                 m_last_texco_num = 0;
393                 m_last_attrib_num = 0;
394         }
395 }
396