Cycles: don't use glsl in textured draw mode, to keep things simpler and faster
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_OpenGLRasterizer.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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
29 /** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
30  *  \ingroup bgerastogl
31  */
32
33  
34 #include <math.h>
35 #include <stdlib.h>
36  
37 #include "RAS_OpenGLRasterizer.h"
38
39 #include "GL/glew.h"
40
41 #include "RAS_Rect.h"
42 #include "RAS_TexVert.h"
43 #include "RAS_MeshObject.h"
44 #include "MT_CmMatrix4x4.h"
45 #include "RAS_IRenderTools.h" // rendering text
46
47 #include "GPU_draw.h"
48 #include "GPU_material.h"
49 #include "GPU_extensions.h"
50
51 #include "DNA_image_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_material_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_scene_types.h"
56
57 #include "BKE_DerivedMesh.h"
58
59 #ifndef M_PI
60 #define M_PI            3.14159265358979323846
61 #endif
62
63 /**
64  *  32x32 bit masks for vinterlace stereo mode
65  */
66 static GLuint left_eye_vinterlace_mask[32];
67 static GLuint right_eye_vinterlace_mask[32];
68
69 /**
70  *  32x32 bit masks for hinterlace stereo mode.
71  *  Left eye = &hinterlace_mask[0]
72  *  Right eye = &hinterlace_mask[1]
73  */
74 static GLuint hinterlace_mask[33];
75
76 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
77         :RAS_IRasterizer(canvas),
78         m_2DCanvas(canvas),
79         m_fogenabled(false),
80         m_time(0.0),
81         m_campos(0.0f, 0.0f, 0.0f),
82         m_camortho(false),
83         m_stereomode(RAS_STEREO_NOSTEREO),
84         m_curreye(RAS_STEREO_LEFTEYE),
85         m_eyeseparation(0.0),
86         m_focallength(0.0),
87         m_setfocallength(false),
88         m_noOfScanlines(32),
89         m_motionblur(0),
90         m_motionblurvalue(-1.0),
91         m_texco_num(0),
92         m_attrib_num(0),
93         //m_last_alphablend(GPU_BLEND_SOLID),
94         m_last_frontface(true),
95         m_materialCachingInfo(0)
96 {
97         m_viewmatrix.setIdentity();
98         m_viewinvmatrix.setIdentity();
99         
100         for (int i = 0; i < 32; i++)
101         {
102                 left_eye_vinterlace_mask[i] = 0x55555555;
103                 right_eye_vinterlace_mask[i] = 0xAAAAAAAA;
104                 hinterlace_mask[i] = (i&1)*0xFFFFFFFF;
105         }
106         hinterlace_mask[32] = 0;
107
108         m_prevafvalue = GPU_get_anisotropic();
109 }
110
111
112
113 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
114 {
115         // Restore the previous AF value
116         GPU_set_anisotropic(m_prevafvalue);
117 }
118
119 bool RAS_OpenGLRasterizer::Init()
120 {
121         GPU_state_init();
122
123
124         m_ambr = 0.0f;
125         m_ambg = 0.0f;
126         m_ambb = 0.0f;
127
128         glDisable(GL_BLEND);
129         glDisable(GL_ALPHA_TEST);
130         //m_last_alphablend = GPU_BLEND_SOLID;
131         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
132
133         glFrontFace(GL_CCW);
134         m_last_frontface = true;
135
136         m_redback = 0.4375;
137         m_greenback = 0.4375;
138         m_blueback = 0.4375;
139         m_alphaback = 0.0;
140
141         glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
142         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
143         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
144
145
146         glShadeModel(GL_SMOOTH);
147
148         return true;
149 }
150
151
152 void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue)
153 {
154         m_ambr = red;
155         m_ambg = green;
156         m_ambb = blue;
157 }
158
159
160 void RAS_OpenGLRasterizer::SetAmbient(float factor)
161 {
162         float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f };
163         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
164 }
165
166
167 void RAS_OpenGLRasterizer::SetBackColor(float red,
168                                                                                 float green,
169                                                                                 float blue,
170                                                                                 float alpha)
171 {
172         m_redback = red;
173         m_greenback = green;
174         m_blueback = blue;
175         m_alphaback = alpha;
176 }
177
178
179
180 void RAS_OpenGLRasterizer::SetFogColor(float r,
181                                                                            float g,
182                                                                            float b)
183 {
184         m_fogr = r;
185         m_fogg = g;
186         m_fogb = b;
187         m_fogenabled = true;
188 }
189
190
191
192 void RAS_OpenGLRasterizer::SetFogStart(float start)
193 {
194         m_fogstart = start;
195         m_fogenabled = true;
196 }
197
198
199
200 void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
201 {
202         m_fogdist = fogend;
203         m_fogenabled = true;
204 }
205
206
207
208 void RAS_OpenGLRasterizer::SetFog(float start,
209                                                                   float dist,
210                                                                   float r,
211                                                                   float g,
212                                                                   float b)
213 {
214         m_fogstart = start;
215         m_fogdist = dist;
216         m_fogr = r;
217         m_fogg = g;
218         m_fogb = b;
219         m_fogenabled = true;
220 }
221
222
223
224 void RAS_OpenGLRasterizer::DisableFog()
225 {
226         m_fogenabled = false;
227 }
228
229 bool RAS_OpenGLRasterizer::IsFogEnabled()
230 {
231         return m_fogenabled;
232 }
233
234
235 void RAS_OpenGLRasterizer::DisplayFog()
236 {
237         if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
238         {
239                 float params[5];
240                 glFogi(GL_FOG_MODE, GL_LINEAR);
241                 glFogf(GL_FOG_DENSITY, 0.1f);
242                 glFogf(GL_FOG_START, m_fogstart);
243                 glFogf(GL_FOG_END, m_fogstart + m_fogdist);
244                 params[0]= m_fogr;
245                 params[1]= m_fogg;
246                 params[2]= m_fogb;
247                 params[3]= 0.0;
248                 glFogfv(GL_FOG_COLOR, params); 
249                 glEnable(GL_FOG);
250         } 
251         else
252         {
253                 glDisable(GL_FOG);
254         }
255 }
256
257
258
259 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
260 {
261         return mat.Activate(this, m_materialCachingInfo);
262 }
263
264
265
266 void RAS_OpenGLRasterizer::Exit()
267 {
268
269         glEnable(GL_CULL_FACE);
270         glEnable(GL_DEPTH_TEST);
271         glClearDepth(1.0); 
272         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
273         glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
274         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
275         glDepthMask (GL_TRUE);
276         glDepthFunc(GL_LEQUAL);
277         glBlendFunc(GL_ONE, GL_ZERO);
278         
279         glDisable(GL_POLYGON_STIPPLE);
280         
281         glDisable(GL_LIGHTING);
282         if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
283                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
284         
285         EndFrame();
286 }
287
288 bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
289 {
290         m_time = time;
291         m_drawingmode = drawingmode;
292
293         // Blender camera routine destroys the settings
294         if (m_drawingmode < KX_SOLID)
295         {
296                 glDisable (GL_CULL_FACE);
297                 glDisable (GL_DEPTH_TEST);
298         }
299         else
300         {
301                 glEnable(GL_DEPTH_TEST);
302                 glEnable (GL_CULL_FACE);
303         }
304
305         glDisable(GL_BLEND);
306         glDisable(GL_ALPHA_TEST);
307         //m_last_alphablend = GPU_BLEND_SOLID;
308         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
309
310         glFrontFace(GL_CCW);
311         m_last_frontface = true;
312
313         glShadeModel(GL_SMOOTH);
314
315         glEnable(GL_MULTISAMPLE_ARB);
316
317         m_2DCanvas->BeginFrame();
318         
319         return true;
320 }
321
322
323
324 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
325 {
326         m_drawingmode = drawingmode;
327
328         if(m_drawingmode == KX_WIREFRAME)
329                 glDisable(GL_CULL_FACE);
330 }
331
332 int RAS_OpenGLRasterizer::GetDrawingMode()
333 {
334         return m_drawingmode;
335 }
336
337
338 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
339 {
340         glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
341 }
342
343
344 void RAS_OpenGLRasterizer::ClearColorBuffer()
345 {
346         m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
347         m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
348 }
349
350
351 void RAS_OpenGLRasterizer::ClearDepthBuffer()
352 {
353         m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
354 }
355
356
357 void RAS_OpenGLRasterizer::ClearCachingInfo(void)
358 {
359         m_materialCachingInfo = 0;
360 }
361
362 void RAS_OpenGLRasterizer::FlushDebugShapes()
363 {
364         if(!m_debugShapes.size())
365                 return;
366
367         // DrawDebugLines
368         GLboolean light, tex;
369
370         light= glIsEnabled(GL_LIGHTING);
371         tex= glIsEnabled(GL_TEXTURE_2D);
372
373         if(light) glDisable(GL_LIGHTING);
374         if(tex) glDisable(GL_TEXTURE_2D);
375
376         //draw lines
377         glBegin(GL_LINES);
378         for (unsigned int i=0;i<m_debugShapes.size();i++)
379         {
380                 if (m_debugShapes[i].m_type != OglDebugShape::LINE)
381                         continue;
382                 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
383                 const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x();
384                 const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x();
385                 glVertex3dv(fromPtr);
386                 glVertex3dv(toPtr);
387         }
388         glEnd();
389
390         //draw circles
391         for (unsigned int i=0;i<m_debugShapes.size();i++)
392         {
393                 if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE)
394                         continue;
395                 glBegin(GL_LINE_LOOP);
396                 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
397
398                 static const MT_Vector3 worldUp(0.,0.,1.);
399                 MT_Vector3 norm = m_debugShapes[i].m_param;
400                 MT_Matrix3x3 tr;
401                 if (norm.fuzzyZero() || norm == worldUp)
402                 {
403                         tr.setIdentity();
404                 }
405                 else
406                 {
407                         MT_Vector3 xaxis, yaxis;
408                         xaxis = MT_cross(norm, worldUp);
409                         yaxis = MT_cross(xaxis, norm);
410                         tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(),
411                                 yaxis.x(), yaxis.y(), yaxis.z(),
412                                 norm.x(), norm.y(), norm.z());
413                 }
414                 MT_Scalar rad = m_debugShapes[i].m_param2.x();
415                 int n = (int) m_debugShapes[i].m_param2.y();
416                 for (int j = 0; j<n; j++)
417                 {
418                         MT_Scalar theta = j*M_PI*2/n;
419                         MT_Vector3 pos(cos(theta)*rad, sin(theta)*rad, 0.);
420                         pos = pos*tr;
421                         pos += m_debugShapes[i].m_pos;
422                         const MT_Scalar* posPtr = &pos.x();
423                         glVertex3dv(posPtr);
424                 }
425                 glEnd();
426         }
427
428         if(light) glEnable(GL_LIGHTING);
429         if(tex) glEnable(GL_TEXTURE_2D);
430
431         m_debugShapes.clear();
432 }
433
434 void RAS_OpenGLRasterizer::EndFrame()
435 {
436         FlushDebugShapes();
437
438         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
439
440         glDisable(GL_MULTISAMPLE_ARB);
441
442         m_2DCanvas->EndFrame();
443 }       
444
445 void RAS_OpenGLRasterizer::SetRenderArea()
446 {
447         RAS_Rect area;
448         // only above/below stereo method needs viewport adjustment
449         switch (m_stereomode)
450         {
451                 case RAS_STEREO_ABOVEBELOW:
452                         switch(m_curreye)
453                         {
454                                 case RAS_STEREO_LEFTEYE:
455                                         // upper half of window
456                                         area.SetLeft(0);
457                                         area.SetBottom(m_2DCanvas->GetHeight() -
458                                                 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
459         
460                                         area.SetRight(int(m_2DCanvas->GetWidth()));
461                                         area.SetTop(int(m_2DCanvas->GetHeight()));
462                                         m_2DCanvas->SetDisplayArea(&area);
463                                         break;
464                                 case RAS_STEREO_RIGHTEYE:
465                                         // lower half of window
466                                         area.SetLeft(0);
467                                         area.SetBottom(0);
468                                         area.SetRight(int(m_2DCanvas->GetWidth()));
469                                         area.SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
470                                         m_2DCanvas->SetDisplayArea(&area);
471                                         break;
472                         }
473                         break;
474                 case RAS_STEREO_SIDEBYSIDE:
475                         switch (m_curreye)
476                         {
477                                 case RAS_STEREO_LEFTEYE:
478                                         // Left half of window
479                                         area.SetLeft(0);
480                                         area.SetBottom(0);
481                                         area.SetRight(m_2DCanvas->GetWidth()/2);
482                                         area.SetTop(m_2DCanvas->GetHeight());
483                                         m_2DCanvas->SetDisplayArea(&area);
484                                         break;
485                                 case RAS_STEREO_RIGHTEYE:
486                                         // Right half of window
487                                         area.SetLeft(m_2DCanvas->GetWidth()/2);
488                                         area.SetBottom(0);
489                                         area.SetRight(m_2DCanvas->GetWidth());
490                                         area.SetTop(m_2DCanvas->GetHeight());
491                                         m_2DCanvas->SetDisplayArea(&area);
492                                         break;
493                         }
494                         break;
495                 default:
496                         // every available pixel
497                         area.SetLeft(0);
498                         area.SetBottom(0);
499                         area.SetRight(int(m_2DCanvas->GetWidth()));
500                         area.SetTop(int(m_2DCanvas->GetHeight()));
501                         m_2DCanvas->SetDisplayArea(&area);
502                         break;
503         }
504 }
505         
506 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
507 {
508         m_stereomode = stereomode;
509 }
510
511 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
512 {
513         return m_stereomode;
514 }
515
516 bool RAS_OpenGLRasterizer::Stereo()
517 {
518         if(m_stereomode > RAS_STEREO_NOSTEREO) // > 0
519                 return true;
520         else
521                 return false;
522 }
523
524 bool RAS_OpenGLRasterizer::InterlacedStereo()
525 {
526         return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
527 }
528
529 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
530 {
531         m_curreye = eye;
532         switch (m_stereomode)
533         {
534                 case RAS_STEREO_QUADBUFFERED:
535                         glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
536                         break;
537                 case RAS_STEREO_ANAGLYPH:
538                         if (m_curreye == RAS_STEREO_LEFTEYE)
539                         {
540                                 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
541                         } else {
542                                 //glAccum(GL_LOAD, 1.0);
543                                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
544                                 ClearDepthBuffer();
545                         }
546                         break;
547                 case RAS_STEREO_VINTERLACE:
548                 {
549                         glEnable(GL_POLYGON_STIPPLE);
550                         glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
551                         if (m_curreye == RAS_STEREO_RIGHTEYE)
552                                 ClearDepthBuffer();
553                         break;
554                 }
555                 case RAS_STEREO_INTERLACED:
556                 {
557                         glEnable(GL_POLYGON_STIPPLE);
558                         glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
559                         if (m_curreye == RAS_STEREO_RIGHTEYE)
560                                 ClearDepthBuffer();
561                         break;
562                 }
563                 default:
564                         break;
565         }
566 }
567
568 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
569 {
570         return m_curreye;
571 }
572
573
574 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
575 {
576         m_eyeseparation = eyeseparation;
577 }
578
579 float RAS_OpenGLRasterizer::GetEyeSeparation()
580 {
581         return m_eyeseparation;
582 }
583
584 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
585 {
586         m_focallength = focallength;
587         m_setfocallength = true;
588 }
589
590 float RAS_OpenGLRasterizer::GetFocalLength()
591 {
592         return m_focallength;
593 }
594
595
596 void RAS_OpenGLRasterizer::SwapBuffers()
597 {
598         m_2DCanvas->SwapBuffers();
599 }
600
601
602
603 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
604 {
605         return m_viewmatrix;
606 }
607
608 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
609 {
610         return m_viewinvmatrix;
611 }
612
613 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
614                                                                         class RAS_IPolyMaterial* polymat,
615                                                                         class RAS_IRenderTools* rendertools)
616
617         bool obcolor = ms.m_bObjectColor;
618         MT_Vector4& rgba = ms.m_RGBAcolor;
619         RAS_MeshSlot::iterator it;
620
621         // handle object color
622         if (obcolor) {
623                 glDisableClientState(GL_COLOR_ARRAY);
624                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
625         }
626         else
627                 glEnableClientState(GL_COLOR_ARRAY);
628
629         for(ms.begin(it); !ms.end(it); ms.next(it)) {
630                 RAS_TexVert *vertex;
631                 size_t i, j, numvert;
632                 
633                 numvert = it.array->m_type;
634
635                 if(it.array->m_type == RAS_DisplayArray::LINE) {
636                         // line drawing, no text
637                         glBegin(GL_LINES);
638
639                         for(i=0; i<it.totindex; i+=2)
640                         {
641                                 vertex = &it.vertex[it.index[i]];
642                                 glVertex3fv(vertex->getXYZ());
643
644                                 vertex = &it.vertex[it.index[i+1]];
645                                 glVertex3fv(vertex->getXYZ());
646                         }
647
648                         glEnd();
649                 }
650                 else {
651                         // triangle and quad text drawing
652                         for(i=0; i<it.totindex; i+=numvert)
653                         {
654                                 float v[4][3];
655                                 int glattrib, unit;
656
657                                 for(j=0; j<numvert; j++) {
658                                         vertex = &it.vertex[it.index[i+j]];
659
660                                         v[j][0] = vertex->getXYZ()[0];
661                                         v[j][1] = vertex->getXYZ()[1];
662                                         v[j][2] = vertex->getXYZ()[2];
663                                 }
664
665                                 // find the right opengl attribute
666                                 glattrib = -1;
667                                 if(GLEW_ARB_vertex_program)
668                                         for(unit=0; unit<m_attrib_num; unit++)
669                                                 if(m_attrib[unit] == RAS_TEXCO_UV1)
670                                                         glattrib = unit;
671                                 
672                                 rendertools->RenderText(polymat->GetDrawingMode(), polymat,
673                                         v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib);
674
675                                 ClearCachingInfo();
676                         }
677                 }
678         }
679
680         glDisableClientState(GL_COLOR_ARRAY);
681 }
682
683 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
684 {
685         m_texco_num = num;
686         if(m_texco_num > RAS_MAX_TEXCO)
687                 m_texco_num = RAS_MAX_TEXCO;
688 }
689
690 void RAS_OpenGLRasterizer::SetAttribNum(int num)
691 {
692         m_attrib_num = num;
693         if(m_attrib_num > RAS_MAX_ATTRIB)
694                 m_attrib_num = RAS_MAX_ATTRIB;
695 }
696
697 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
698 {
699         // this changes from material to material
700         if(unit < RAS_MAX_TEXCO)
701                 m_texco[unit] = coords;
702 }
703
704 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit)
705 {
706         // this changes from material to material
707         if(unit < RAS_MAX_ATTRIB)
708                 m_attrib[unit] = coords;
709 }
710
711 void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
712 {
713         int unit;
714
715         if(GLEW_ARB_multitexture) {
716                 for(unit=0; unit<m_texco_num; unit++) {
717                         if(tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
718                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
719                                 continue;
720                         }
721                         switch(m_texco[unit]) {
722                         case RAS_TEXCO_ORCO:
723                         case RAS_TEXCO_GLOB:
724                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
725                                 break;
726                         case RAS_TEXCO_UV1:
727                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
728                                 break;
729                         case RAS_TEXCO_NORM:
730                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal());
731                                 break;
732                         case RAS_TEXTANGENT:
733                                 glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent());
734                                 break;
735                         case RAS_TEXCO_UV2:
736                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
737                                 break;
738                         default:
739                                 break;
740                         }
741                 }
742         }
743
744         if(GLEW_ARB_vertex_program) {
745                 for(unit=0; unit<m_attrib_num; unit++) {
746                         switch(m_attrib[unit]) {
747                         case RAS_TEXCO_ORCO:
748                         case RAS_TEXCO_GLOB:
749                                 glVertexAttrib3fvARB(unit, tv.getXYZ());
750                                 break;
751                         case RAS_TEXCO_UV1:
752                                 glVertexAttrib2fvARB(unit, tv.getUV1());
753                                 break;
754                         case RAS_TEXCO_NORM:
755                                 glVertexAttrib3fvARB(unit, tv.getNormal());
756                                 break;
757                         case RAS_TEXTANGENT:
758                                 glVertexAttrib4fvARB(unit, tv.getTangent());
759                                 break;
760                         case RAS_TEXCO_UV2:
761                                 glVertexAttrib2fvARB(unit, tv.getUV2());
762                                 break;
763                         case RAS_TEXCO_VCOL:
764                                 glVertexAttrib4ubvARB(unit, tv.getRGBA());
765                                 break;
766                         default:
767                                 break;
768                         }
769                 }
770         }
771
772 }
773
774 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
775 {
776         IndexPrimitivesInternal(ms, false);
777 }
778
779 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
780 {
781         IndexPrimitivesInternal(ms, true);
782 }
783
784 static bool current_wireframe;
785 static RAS_MaterialBucket *current_bucket;
786 static RAS_IPolyMaterial *current_polymat;
787 static RAS_MeshSlot *current_ms;
788 static RAS_MeshObject *current_mesh;
789 static int current_blmat_nr;
790 static GPUVertexAttribs current_gpu_attribs;
791 static Image *current_image;
792 static int CheckMaterialDM(int matnr, void *attribs)
793 {
794         // only draw the current material
795         if (matnr != current_blmat_nr)
796                 return 0;
797         GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
798         if (gattribs)
799                 memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
800         return 1;
801 }
802
803 /*
804 static int CheckTexfaceDM(void *mcol, int index)
805 {
806
807         // index is the original face index, retrieve the polygon
808         RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
809                 current_mesh->GetPolygon(index) : NULL;
810         if (polygon && polygon->GetMaterial() == current_bucket) {
811                 // must handle color.
812                 if (current_wireframe)
813                         return 2;
814                 if (current_ms->m_bObjectColor) {
815                         MT_Vector4& rgba = current_ms->m_RGBAcolor;
816                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
817                         // don't use mcol
818                         return 2;
819                 }
820                 if (!mcol) {
821                         // we have to set the color from the material
822                         unsigned char rgba[4];
823                         current_polymat->GetMaterialRGBAColor(rgba);
824                         glColor4ubv((const GLubyte *)rgba);
825                         return 2;
826                 }
827                 return 1;
828         }
829         return 0;
830 }
831 */
832
833 static int CheckTexDM(MTFace *tface, int has_mcol, int matnr)
834 {
835
836         // index is the original face index, retrieve the polygon
837         if (matnr == current_blmat_nr &&
838                 (tface == NULL || tface->tpage == current_image)) {
839                 // must handle color.
840                 if (current_wireframe)
841                         return 2;
842                 if (current_ms->m_bObjectColor) {
843                         MT_Vector4& rgba = current_ms->m_RGBAcolor;
844                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
845                         // don't use mcol
846                         return 2;
847                 }
848                 if (!has_mcol) {
849                         // we have to set the color from the material
850                         unsigned char rgba[4];
851                         current_polymat->GetMaterialRGBAColor(rgba);
852                         glColor4ubv((const GLubyte *)rgba);
853                         return 2;
854                 }
855                 return 1;
856         }
857         return 0;
858 }
859
860 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
861
862         bool obcolor = ms.m_bObjectColor;
863         bool wireframe = m_drawingmode <= KX_WIREFRAME;
864         MT_Vector4& rgba = ms.m_RGBAcolor;
865         RAS_MeshSlot::iterator it;
866
867         if (ms.m_pDerivedMesh) {
868                 // mesh data is in derived mesh, 
869                 current_bucket = ms.m_bucket;
870                 current_polymat = current_bucket->GetPolyMaterial();
871                 current_ms = &ms;
872                 current_mesh = ms.m_mesh;
873                 current_wireframe = wireframe;
874                 // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
875
876                 // handle two-side
877                 if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
878                         this->SetCullFace(true);
879                 else
880                         this->SetCullFace(false);
881
882                 if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
883                         // GetMaterialIndex return the original mface material index, 
884                         // increment by 1 to match what derived mesh is doing
885                         current_blmat_nr = current_polymat->GetMaterialIndex()+1;
886                         // For GLSL we need to retrieve the GPU material attribute
887                         Material* blmat = current_polymat->GetBlenderMaterial();
888                         Scene* blscene = current_polymat->GetBlenderScene();
889                         if (!wireframe && blscene && blmat)
890                                 GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), &current_gpu_attribs);
891                         else
892                                 memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
893                         // DM draw can mess up blending mode, restore at the end
894                         int current_blend_mode = GPU_get_material_alpha_blend();
895                         ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
896                         GPU_set_material_alpha_blend(current_blend_mode);
897                 } else {
898                         //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
899                         current_blmat_nr = current_polymat->GetMaterialIndex();
900                         current_image = current_polymat->GetBlenderImage();
901                         ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM);
902                 }
903                 return;
904         }
905         // iterate over display arrays, each containing an index + vertex array
906         for(ms.begin(it); !ms.end(it); ms.next(it)) {
907                 RAS_TexVert *vertex;
908                 size_t i, j, numvert;
909                 
910                 numvert = it.array->m_type;
911
912                 if(it.array->m_type == RAS_DisplayArray::LINE) {
913                         // line drawing
914                         glBegin(GL_LINES);
915
916                         for(i=0; i<it.totindex; i+=2)
917                         {
918                                 vertex = &it.vertex[it.index[i]];
919                                 glVertex3fv(vertex->getXYZ());
920
921                                 vertex = &it.vertex[it.index[i+1]];
922                                 glVertex3fv(vertex->getXYZ());
923                         }
924
925                         glEnd();
926                 }
927                 else {
928                         // triangle and quad drawing
929                         if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
930                                 glBegin(GL_TRIANGLES);
931                         else
932                                 glBegin(GL_QUADS);
933
934                         for(i=0; i<it.totindex; i+=numvert)
935                         {
936                                 if(obcolor)
937                                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
938
939                                 for(j=0; j<numvert; j++) {
940                                         vertex = &it.vertex[it.index[i+j]];
941
942                                         if(!wireframe) {
943                                                 if(!obcolor)
944                                                         glColor4ubv((const GLubyte *)(vertex->getRGBA()));
945
946                                                 glNormal3fv(vertex->getNormal());
947
948                                                 if(multi)
949                                                         TexCoord(*vertex);
950                                                 else
951                                                         glTexCoord2fv(vertex->getUV1());
952                                         }
953
954                                         glVertex3fv(vertex->getXYZ());
955                                 }
956                         }
957
958                         glEnd();
959                 }
960         }
961 }
962
963 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
964 {
965         glMatrixMode(GL_PROJECTION);
966         double* matrix = &mat(0,0);
967         glLoadMatrixd(matrix);
968
969         m_camortho= (mat(3, 3) != 0.0f);
970 }
971
972 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
973 {
974         glMatrixMode(GL_PROJECTION);
975         double matrix[16];
976         /* Get into argument. Looks a bit dodgy, but it's ok. */
977         mat.getValue(matrix);
978         /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
979         glLoadMatrixd(matrix);  
980
981         m_camortho= (mat[3][3] != 0.0f);
982 }
983
984 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
985         float left,
986         float right,
987         float bottom,
988         float top,
989         float frustnear,
990         float frustfar,
991         float focallength,
992         bool 
993 ){
994         MT_Matrix4x4 result;
995         double mat[16];
996
997         // correction for stereo
998         if(Stereo())
999         {
1000                         float near_div_focallength;
1001                         float offset;
1002
1003                         // if Rasterizer.setFocalLength is not called we use the camera focallength
1004                         if (!m_setfocallength)
1005                                 // if focallength is null we use a value known to be reasonable
1006                                 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0
1007                                         : focallength;
1008
1009                         near_div_focallength = frustnear / m_focallength;
1010                         offset = 0.5 * m_eyeseparation * near_div_focallength;
1011                         switch(m_curreye)
1012                         {
1013                                 case RAS_STEREO_LEFTEYE:
1014                                                 left += offset;
1015                                                 right += offset;
1016                                                 break;
1017                                 case RAS_STEREO_RIGHTEYE:
1018                                                 left -= offset;
1019                                                 right -= offset;
1020                                                 break;
1021                         }
1022                         // leave bottom and top untouched
1023         }
1024         
1025         glMatrixMode(GL_PROJECTION);
1026         glLoadIdentity();
1027         glFrustum(left, right, bottom, top, frustnear, frustfar);
1028                 
1029         glGetDoublev(GL_PROJECTION_MATRIX, mat);
1030         result.setValue(mat);
1031
1032         return result;
1033 }
1034
1035 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
1036         float left,
1037         float right,
1038         float bottom,
1039         float top,
1040         float frustnear,
1041         float frustfar
1042 ){
1043         MT_Matrix4x4 result;
1044         double mat[16];
1045
1046         // stereo is meaning less for orthographic, disable it
1047         glMatrixMode(GL_PROJECTION);
1048         glLoadIdentity();
1049         glOrtho(left, right, bottom, top, frustnear, frustfar);
1050                 
1051         glGetDoublev(GL_PROJECTION_MATRIX, mat);
1052         result.setValue(mat);
1053
1054         return result;
1055 }
1056
1057
1058 // next arguments probably contain redundant info, for later...
1059 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, 
1060                                                                                  const MT_Matrix3x3 & camOrientMat3x3,
1061                                                                                  const MT_Point3 & pos,
1062                                                                                  bool perspective)
1063 {
1064         m_viewmatrix = mat;
1065
1066         // correction for stereo
1067         if(Stereo() && perspective)
1068         {
1069                 MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
1070                 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
1071                 MT_Vector3 viewDir, viewupVec;
1072                 MT_Vector3 eyeline;
1073
1074                 // actual viewDir
1075                 viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
1076                 // actual viewup vec
1077                 viewupVec = camOrientMat3x3 * unitViewupVec;
1078
1079                 // vector between eyes
1080                 eyeline = viewDir.cross(viewupVec);
1081
1082                 switch(m_curreye)
1083                 {
1084                         case RAS_STEREO_LEFTEYE:
1085                                 {
1086                                 // translate to left by half the eye distance
1087                                 MT_Transform transform;
1088                                 transform.setIdentity();
1089                                 transform.translate(-(eyeline * m_eyeseparation / 2.0));
1090                                 m_viewmatrix *= transform;
1091                                 }
1092                                 break;
1093                         case RAS_STEREO_RIGHTEYE:
1094                                 {
1095                                 // translate to right by half the eye distance
1096                                 MT_Transform transform;
1097                                 transform.setIdentity();
1098                                 transform.translate(eyeline * m_eyeseparation / 2.0);
1099                                 m_viewmatrix *= transform;
1100                                 }
1101                                 break;
1102                 }
1103         }
1104
1105         m_viewinvmatrix = m_viewmatrix;
1106         m_viewinvmatrix.invert();
1107
1108         // note: getValue gives back column major as needed by OpenGL
1109         MT_Scalar glviewmat[16];
1110         m_viewmatrix.getValue(glviewmat);
1111
1112         glMatrixMode(GL_MODELVIEW);
1113         glLoadMatrixd(glviewmat);
1114         m_campos = pos;
1115 }
1116
1117
1118 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
1119 {
1120         return m_campos;
1121 }
1122
1123 bool RAS_OpenGLRasterizer::GetCameraOrtho()
1124 {
1125         return m_camortho;
1126 }
1127
1128 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
1129 {
1130         if (enable)
1131                 glEnable(GL_CULL_FACE);
1132         else
1133                 glDisable(GL_CULL_FACE);
1134 }
1135
1136 void RAS_OpenGLRasterizer::SetLines(bool enable)
1137 {
1138         if (enable)
1139                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1140         else
1141                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1142 }
1143
1144 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
1145                                                                                   float specY,
1146                                                                                   float specZ,
1147                                                                                   float specval)
1148 {
1149         GLfloat mat_specular[] = {specX, specY, specZ, specval};
1150         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1151 }
1152
1153
1154
1155 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
1156 {
1157         GLfloat mat_shininess[] = {     shiny };
1158         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1159 }
1160
1161
1162
1163 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
1164 {
1165         GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
1166         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
1167 }
1168
1169 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
1170 {
1171         GLfloat mat_emit [] = {eX,eY,eZ,e};
1172         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
1173 }
1174
1175
1176 double RAS_OpenGLRasterizer::GetTime()
1177 {
1178         return m_time;
1179 }
1180
1181 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
1182 {
1183         glPolygonOffset(mult, add);
1184         GLint mode = GL_POLYGON_OFFSET_FILL;
1185         if (m_drawingmode < KX_SHADED)
1186                 mode = GL_POLYGON_OFFSET_LINE;
1187         if (mult != 0.0f || add != 0.0f)
1188                 glEnable(mode);
1189         else
1190                 glDisable(mode);
1191 }
1192
1193 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
1194 {
1195         /* don't just set m_motionblur to 1, but check if it is 0 so
1196          * we don't reset a motion blur that is already enabled */
1197         if(m_motionblur == 0)
1198                 m_motionblur = 1;
1199         m_motionblurvalue = motionblurvalue;
1200 }
1201
1202 void RAS_OpenGLRasterizer::DisableMotionBlur()
1203 {
1204         m_motionblur = 0;
1205         m_motionblurvalue = -1.0;
1206 }
1207
1208 void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend)
1209 {
1210         GPU_set_material_alpha_blend(alphablend);
1211 /*
1212         if(alphablend == m_last_alphablend)
1213                 return;
1214
1215         if(alphablend == GPU_BLEND_SOLID) {
1216                 glDisable(GL_BLEND);
1217                 glDisable(GL_ALPHA_TEST);
1218                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1219         }
1220         else if(alphablend == GPU_BLEND_ADD) {
1221                 glBlendFunc(GL_ONE, GL_ONE);
1222                 glEnable(GL_BLEND);
1223                 glDisable(GL_ALPHA_TEST);
1224         }
1225         else if(alphablend == GPU_BLEND_ALPHA) {
1226                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1227                 glEnable(GL_BLEND);
1228                 glEnable(GL_ALPHA_TEST);
1229                 glAlphaFunc(GL_GREATER, 0.0f);
1230         }
1231         else if(alphablend == GPU_BLEND_CLIP) {
1232                 glDisable(GL_BLEND); 
1233                 glEnable(GL_ALPHA_TEST);
1234                 glAlphaFunc(GL_GREATER, 0.5f);
1235         }
1236
1237         m_last_alphablend = alphablend;
1238 */
1239 }
1240
1241 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
1242 {
1243         if(m_last_frontface == ccw)
1244                 return;
1245
1246         if(ccw)
1247                 glFrontFace(GL_CCW);
1248         else
1249                 glFrontFace(GL_CW);
1250         
1251         m_last_frontface = ccw;
1252 }
1253
1254 void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level)
1255 {
1256         GPU_set_anisotropic((float)level);
1257 }
1258
1259 short RAS_OpenGLRasterizer::GetAnisotropicFiltering()
1260 {
1261         return (short)GPU_get_anisotropic();
1262 }