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