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