c2859394176d9d5e68487ee9e529b43309452b20
[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 Image *current_image;
735 static int CheckMaterialDM(int matnr, void *attribs)
736 {
737         // only draw the current material
738         if (matnr != current_blmat_nr)
739                 return 0;
740         GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
741         if (gattribs)
742                 memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
743         return 1;
744 }
745 static int CheckTexfaceDM(void *mcol, int index)
746 {
747
748         // index is the original face index, retrieve the polygon
749         RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
750                 current_mesh->GetPolygon(index) : NULL;
751         if (polygon && polygon->GetMaterial() == current_bucket) {
752                 // must handle color.
753                 if (current_wireframe)
754                         return 2;
755                 if (current_ms->m_bObjectColor) {
756                         MT_Vector4& rgba = current_ms->m_RGBAcolor;
757                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
758                         // don't use mcol
759                         return 2;
760                 }
761                 if (!mcol) {
762                         // we have to set the color from the material
763                         unsigned char rgba[4];
764                         current_polymat->GetMaterialRGBAColor(rgba);
765                         glColor4ubv((const GLubyte *)rgba);
766                         return 2;
767                 }
768                 return 1;
769         }
770         return 0;
771 }
772
773 static int CheckTexDM(MTFace *tface, MCol *mcol, int matnr)
774 {
775
776         // index is the original face index, retrieve the polygon
777         if (matnr == current_blmat_nr &&
778                 (tface == NULL || tface->tpage == current_image)) {
779                 // must handle color.
780                 if (current_wireframe)
781                         return 2;
782                 if (current_ms->m_bObjectColor) {
783                         MT_Vector4& rgba = current_ms->m_RGBAcolor;
784                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
785                         // don't use mcol
786                         return 2;
787                 }
788                 if (!mcol) {
789                         // we have to set the color from the material
790                         unsigned char rgba[4];
791                         current_polymat->GetMaterialRGBAColor(rgba);
792                         glColor4ubv((const GLubyte *)rgba);
793                         return 2;
794                 }
795                 return 1;
796         }
797         return 0;
798 }
799
800 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
801
802         bool obcolor = ms.m_bObjectColor;
803         bool wireframe = m_drawingmode <= KX_WIREFRAME;
804         MT_Vector4& rgba = ms.m_RGBAcolor;
805         RAS_MeshSlot::iterator it;
806
807         if (ms.m_pDerivedMesh) {
808                 // mesh data is in derived mesh, 
809                 current_bucket = ms.m_bucket;
810                 current_polymat = current_bucket->GetPolyMaterial();
811                 current_ms = &ms;
812                 current_mesh = ms.m_mesh;
813                 current_wireframe = wireframe;
814                 MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL);
815
816                 // handle two-side
817                 if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_TWOSIDE)
818                         this->SetCullFace(false);
819                 else
820                         this->SetCullFace(true);
821
822                 if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
823                         // GetMaterialIndex return the original mface material index, 
824                         // increment by 1 to match what derived mesh is doing
825                         current_blmat_nr = current_polymat->GetMaterialIndex()+1;
826                         // For GLSL we need to retrieve the GPU material attribute
827                         Material* blmat = current_polymat->GetBlenderMaterial();
828                         Scene* blscene = current_polymat->GetBlenderScene();
829                         if (!wireframe && blscene && blmat)
830                                 GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), &current_gpu_attribs);
831                         else
832                                 memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
833                         // DM draw can mess up blending mode, restore at the end
834                         int current_blend_mode = GPU_get_material_blend_mode();
835                         ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
836                         GPU_set_material_blend_mode(current_blend_mode);
837                 } else {
838                         //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
839                         current_blmat_nr = current_polymat->GetMaterialIndex();
840                         current_image = current_polymat->GetBlenderImage();
841                         ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM);
842                 }
843                 return;
844         }
845         // iterate over display arrays, each containing an index + vertex array
846         for(ms.begin(it); !ms.end(it); ms.next(it)) {
847                 RAS_TexVert *vertex;
848                 size_t i, j, numvert;
849                 
850                 numvert = it.array->m_type;
851
852                 if(it.array->m_type == RAS_DisplayArray::LINE) {
853                         // line drawing
854                         glBegin(GL_LINES);
855
856                         for(i=0; i<it.totindex; i+=2)
857                         {
858                                 vertex = &it.vertex[it.index[i]];
859                                 glVertex3fv(vertex->getXYZ());
860
861                                 vertex = &it.vertex[it.index[i+1]];
862                                 glVertex3fv(vertex->getXYZ());
863                         }
864
865                         glEnd();
866                 }
867                 else {
868                         // triangle and quad drawing
869                         if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
870                                 glBegin(GL_TRIANGLES);
871                         else
872                                 glBegin(GL_QUADS);
873
874                         for(i=0; i<it.totindex; i+=numvert)
875                         {
876                                 if(obcolor)
877                                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
878
879                                 for(j=0; j<numvert; j++) {
880                                         vertex = &it.vertex[it.index[i+j]];
881
882                                         if(!wireframe) {
883                                                 if(!obcolor)
884                                                         glColor4ubv((const GLubyte *)(vertex->getRGBA()));
885
886                                                 glNormal3fv(vertex->getNormal());
887
888                                                 if(multi)
889                                                         TexCoord(*vertex);
890                                                 else
891                                                         glTexCoord2fv(vertex->getUV1());
892                                         }
893
894                                         glVertex3fv(vertex->getXYZ());
895                                 }
896                         }
897
898                         glEnd();
899                 }
900         }
901 }
902
903 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
904 {
905         glMatrixMode(GL_PROJECTION);
906         double* matrix = &mat(0,0);
907         glLoadMatrixd(matrix);
908
909         m_camortho= (mat(3, 3) != 0.0f);
910 }
911
912 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
913 {
914         glMatrixMode(GL_PROJECTION);
915         double matrix[16];
916         /* Get into argument. Looks a bit dodgy, but it's ok. */
917         mat.getValue(matrix);
918         /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
919         glLoadMatrixd(matrix);  
920
921         m_camortho= (mat[3][3] != 0.0f);
922 }
923
924 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
925         float left,
926         float right,
927         float bottom,
928         float top,
929         float frustnear,
930         float frustfar,
931         float focallength,
932         bool 
933 ){
934         MT_Matrix4x4 result;
935         double mat[16];
936
937         // correction for stereo
938         if(Stereo())
939         {
940                         float near_div_focallength;
941                         float offset;
942
943                         // if Rasterizer.setFocalLength is not called we use the camera focallength
944                         if (!m_setfocallength)
945                                 // if focallength is null we use a value known to be reasonable
946                                 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0
947                                         : focallength;
948
949                         near_div_focallength = frustnear / m_focallength;
950                         offset = 0.5 * m_eyeseparation * near_div_focallength;
951                         switch(m_curreye)
952                         {
953                                 case RAS_STEREO_LEFTEYE:
954                                                 left += offset;
955                                                 right += offset;
956                                                 break;
957                                 case RAS_STEREO_RIGHTEYE:
958                                                 left -= offset;
959                                                 right -= offset;
960                                                 break;
961                         }
962                         // leave bottom and top untouched
963         }
964         
965         glMatrixMode(GL_PROJECTION);
966         glLoadIdentity();
967         glFrustum(left, right, bottom, top, frustnear, frustfar);
968                 
969         glGetDoublev(GL_PROJECTION_MATRIX, mat);
970         result.setValue(mat);
971
972         return result;
973 }
974
975 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
976         float left,
977         float right,
978         float bottom,
979         float top,
980         float frustnear,
981         float frustfar
982 ){
983         MT_Matrix4x4 result;
984         double mat[16];
985
986         // stereo is meaning less for orthographic, disable it
987         glMatrixMode(GL_PROJECTION);
988         glLoadIdentity();
989         glOrtho(left, right, bottom, top, frustnear, frustfar);
990                 
991         glGetDoublev(GL_PROJECTION_MATRIX, mat);
992         result.setValue(mat);
993
994         return result;
995 }
996
997
998 // next arguments probably contain redundant info, for later...
999 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, 
1000                                                                                  const MT_Matrix3x3 & camOrientMat3x3,
1001                                                                                  const MT_Point3 & pos,
1002                                                                                  bool perspective)
1003 {
1004         m_viewmatrix = mat;
1005
1006         // correction for stereo
1007         if(Stereo() && perspective)
1008         {
1009                 MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
1010                 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
1011                 MT_Vector3 viewDir, viewupVec;
1012                 MT_Vector3 eyeline;
1013
1014                 // actual viewDir
1015                 viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
1016                 // actual viewup vec
1017                 viewupVec = camOrientMat3x3 * unitViewupVec;
1018
1019                 // vector between eyes
1020                 eyeline = viewDir.cross(viewupVec);
1021
1022                 switch(m_curreye)
1023                 {
1024                         case RAS_STEREO_LEFTEYE:
1025                                 {
1026                                 // translate to left by half the eye distance
1027                                 MT_Transform transform;
1028                                 transform.setIdentity();
1029                                 transform.translate(-(eyeline * m_eyeseparation / 2.0));
1030                                 m_viewmatrix *= transform;
1031                                 }
1032                                 break;
1033                         case RAS_STEREO_RIGHTEYE:
1034                                 {
1035                                 // translate to right by half the eye distance
1036                                 MT_Transform transform;
1037                                 transform.setIdentity();
1038                                 transform.translate(eyeline * m_eyeseparation / 2.0);
1039                                 m_viewmatrix *= transform;
1040                                 }
1041                                 break;
1042                 }
1043         }
1044
1045         m_viewinvmatrix = m_viewmatrix;
1046         m_viewinvmatrix.invert();
1047
1048         // note: getValue gives back column major as needed by OpenGL
1049         MT_Scalar glviewmat[16];
1050         m_viewmatrix.getValue(glviewmat);
1051
1052         glMatrixMode(GL_MODELVIEW);
1053         glLoadMatrixd(glviewmat);
1054         m_campos = pos;
1055 }
1056
1057
1058 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
1059 {
1060         return m_campos;
1061 }
1062
1063 bool RAS_OpenGLRasterizer::GetCameraOrtho()
1064 {
1065         return m_camortho;
1066 }
1067
1068 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
1069 {
1070         if (enable)
1071                 glEnable(GL_CULL_FACE);
1072         else
1073                 glDisable(GL_CULL_FACE);
1074 }
1075
1076 void RAS_OpenGLRasterizer::SetLines(bool enable)
1077 {
1078         if (enable)
1079                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1080         else
1081                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1082 }
1083
1084 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
1085                                                                                   float specY,
1086                                                                                   float specZ,
1087                                                                                   float specval)
1088 {
1089         GLfloat mat_specular[] = {specX, specY, specZ, specval};
1090         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1091 }
1092
1093
1094
1095 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
1096 {
1097         GLfloat mat_shininess[] = {     shiny };
1098         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1099 }
1100
1101
1102
1103 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
1104 {
1105         GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
1106         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
1107 }
1108
1109 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
1110 {
1111         GLfloat mat_emit [] = {eX,eY,eZ,e};
1112         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
1113 }
1114
1115
1116 double RAS_OpenGLRasterizer::GetTime()
1117 {
1118         return m_time;
1119 }
1120
1121 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
1122 {
1123         glPolygonOffset(mult, add);
1124         GLint mode = GL_POLYGON_OFFSET_FILL;
1125         if (m_drawingmode < KX_SHADED)
1126                 mode = GL_POLYGON_OFFSET_LINE;
1127         if (mult != 0.0f || add != 0.0f)
1128                 glEnable(mode);
1129         else
1130                 glDisable(mode);
1131 }
1132
1133 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
1134 {
1135         /* don't just set m_motionblur to 1, but check if it is 0 so
1136          * we don't reset a motion blur that is already enabled */
1137         if(m_motionblur == 0)
1138                 m_motionblur = 1;
1139         m_motionblurvalue = motionblurvalue;
1140 }
1141
1142 void RAS_OpenGLRasterizer::DisableMotionBlur()
1143 {
1144         m_motionblur = 0;
1145         m_motionblurvalue = -1.0;
1146 }
1147
1148 void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode)
1149 {
1150         GPU_set_material_blend_mode(blendmode);
1151 /*
1152         if(blendmode == m_last_blendmode)
1153                 return;
1154
1155         if(blendmode == GPU_BLEND_SOLID) {
1156                 glDisable(GL_BLEND);
1157                 glDisable(GL_ALPHA_TEST);
1158                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1159         }
1160         else if(blendmode == GPU_BLEND_ADD) {
1161                 glBlendFunc(GL_ONE, GL_ONE);
1162                 glEnable(GL_BLEND);
1163                 glDisable(GL_ALPHA_TEST);
1164         }
1165         else if(blendmode == GPU_BLEND_ALPHA) {
1166                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1167                 glEnable(GL_BLEND);
1168                 glEnable(GL_ALPHA_TEST);
1169                 glAlphaFunc(GL_GREATER, 0.0f);
1170         }
1171         else if(blendmode == GPU_BLEND_CLIP) {
1172                 glDisable(GL_BLEND); 
1173                 glEnable(GL_ALPHA_TEST);
1174                 glAlphaFunc(GL_GREATER, 0.5f);
1175         }
1176
1177         m_last_blendmode = blendmode;
1178 */
1179 }
1180
1181 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
1182 {
1183         if(m_last_frontface == ccw)
1184                 return;
1185
1186         if(ccw)
1187                 glFrontFace(GL_CCW);
1188         else
1189                 glFrontFace(GL_CW);
1190         
1191         m_last_frontface = ccw;
1192 }
1193