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