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