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