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