BGE Rasterizer Cleanup: Removing the need to reference KX_BlenderMaterial or KX_Polyg...
[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 "RAS_LightObject.h"
44 #include "MT_CmMatrix4x4.h"
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         #include "BLF_api.h"
63 }
64
65
66 // XXX Clean these up <<<
67 #include "Value.h"
68 #include "KX_Light.h"
69 #include "KX_Scene.h"
70 #include "KX_RayCast.h"
71 #include "KX_GameObject.h"
72 // >>>
73
74 #ifndef M_PI
75 #define M_PI            3.14159265358979323846
76 #endif
77
78 /**
79  *  32x32 bit masks for vinterlace stereo mode
80  */
81 static GLuint left_eye_vinterlace_mask[32];
82 static GLuint right_eye_vinterlace_mask[32];
83
84 /**
85  *  32x32 bit masks for hinterlace stereo mode.
86  *  Left eye = &hinterlace_mask[0]
87  *  Right eye = &hinterlace_mask[1]
88  */
89 static GLuint hinterlace_mask[33];
90
91 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage)
92         :RAS_IRasterizer(canvas),
93         m_2DCanvas(canvas),
94         m_fogenabled(false),
95         m_time(0.0),
96         m_campos(0.0f, 0.0f, 0.0f),
97         m_camortho(false),
98         m_stereomode(RAS_STEREO_NOSTEREO),
99         m_curreye(RAS_STEREO_LEFTEYE),
100         m_eyeseparation(0.0),
101         m_focallength(0.0),
102         m_setfocallength(false),
103         m_noOfScanlines(32),
104         m_motionblur(0),
105         m_motionblurvalue(-1.0),
106         m_usingoverrideshader(false),
107     m_clientobject(NULL),
108     m_auxilaryClientInfo(NULL),
109         m_texco_num(0),
110         m_attrib_num(0),
111         //m_last_alphablend(GPU_BLEND_SOLID),
112         m_last_frontface(true),
113         m_materialCachingInfo(0),
114         m_storage_type(storage)
115 {
116         m_viewmatrix.setIdentity();
117         m_viewinvmatrix.setIdentity();
118         
119         for (int i = 0; i < 32; i++)
120         {
121                 left_eye_vinterlace_mask[i] = 0x55555555;
122                 right_eye_vinterlace_mask[i] = 0xAAAAAAAA;
123                 hinterlace_mask[i] = (i&1)*0xFFFFFFFF;
124         }
125         hinterlace_mask[32] = 0;
126
127         m_prevafvalue = GPU_get_anisotropic();
128
129         if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/)
130         {
131                 m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
132                 m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
133                 m_storage_type = RAS_VBO;
134         }
135         else if ((m_storage_type == RAS_VA) || (m_storage_type == RAS_AUTO_STORAGE && GLEW_VERSION_1_1))
136         {
137                 m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
138                 m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
139                 m_storage_type = RAS_VA;
140         }
141         else
142         {
143                 m_storage = m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
144                 m_storage_type = RAS_IMMEDIATE;
145         }
146
147         glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights);
148         if (m_numgllights < 8)
149                 m_numgllights = 8;
150 }
151
152
153
154 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
155 {
156         // Restore the previous AF value
157         GPU_set_anisotropic(m_prevafvalue);
158         if (m_failsafe_storage && m_failsafe_storage != m_storage)
159                 delete m_failsafe_storage;
160
161         if (m_storage)
162                 delete m_storage;
163 }
164
165 bool RAS_OpenGLRasterizer::Init()
166 {
167         bool storage_init;
168         GPU_state_init();
169
170
171         m_ambr = 0.0f;
172         m_ambg = 0.0f;
173         m_ambb = 0.0f;
174
175         glDisable(GL_BLEND);
176         glDisable(GL_ALPHA_TEST);
177         //m_last_alphablend = GPU_BLEND_SOLID;
178         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
179
180         glFrontFace(GL_CCW);
181         m_last_frontface = true;
182
183         m_redback = 0.4375;
184         m_greenback = 0.4375;
185         m_blueback = 0.4375;
186         m_alphaback = 0.0;
187
188         glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
189         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
190         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
191
192
193         glShadeModel(GL_SMOOTH);
194
195         storage_init = m_storage->Init();
196
197         return true && storage_init;
198 }
199
200
201 void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue)
202 {
203         m_ambr = red;
204         m_ambg = green;
205         m_ambb = blue;
206 }
207
208
209 void RAS_OpenGLRasterizer::SetAmbient(float factor)
210 {
211         float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f };
212         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
213 }
214
215
216 void RAS_OpenGLRasterizer::SetBackColor(float red,
217                                                                                 float green,
218                                                                                 float blue,
219                                                                                 float alpha)
220 {
221         m_redback = red;
222         m_greenback = green;
223         m_blueback = blue;
224         m_alphaback = alpha;
225 }
226
227
228
229 void RAS_OpenGLRasterizer::SetFogColor(float r,
230                                                                            float g,
231                                                                            float b)
232 {
233         m_fogr = r;
234         m_fogg = g;
235         m_fogb = b;
236         m_fogenabled = true;
237 }
238
239
240
241 void RAS_OpenGLRasterizer::SetFogStart(float start)
242 {
243         m_fogstart = start;
244         m_fogenabled = true;
245 }
246
247
248
249 void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
250 {
251         m_fogdist = fogend;
252         m_fogenabled = true;
253 }
254
255
256
257 void RAS_OpenGLRasterizer::SetFog(float start,
258                                                                   float dist,
259                                                                   float r,
260                                                                   float g,
261                                                                   float b)
262 {
263         m_fogstart = start;
264         m_fogdist = dist;
265         m_fogr = r;
266         m_fogg = g;
267         m_fogb = b;
268         m_fogenabled = true;
269 }
270
271
272
273 void RAS_OpenGLRasterizer::DisableFog()
274 {
275         m_fogenabled = false;
276 }
277
278 bool RAS_OpenGLRasterizer::IsFogEnabled()
279 {
280         return m_fogenabled;
281 }
282
283
284 void RAS_OpenGLRasterizer::DisplayFog()
285 {
286         if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
287         {
288                 float params[5];
289                 glFogi(GL_FOG_MODE, GL_LINEAR);
290                 glFogf(GL_FOG_DENSITY, 0.1f);
291                 glFogf(GL_FOG_START, m_fogstart);
292                 glFogf(GL_FOG_END, m_fogstart + m_fogdist);
293                 params[0] = m_fogr;
294                 params[1] = m_fogg;
295                 params[2] = m_fogb;
296                 params[3] = 0.0;
297                 glFogfv(GL_FOG_COLOR, params); 
298                 glEnable(GL_FOG);
299         } 
300         else
301         {
302                 glDisable(GL_FOG);
303         }
304 }
305
306
307
308 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
309 {
310         return mat.Activate(this, m_materialCachingInfo);
311 }
312
313
314
315 void RAS_OpenGLRasterizer::Exit()
316 {
317
318         m_storage->Exit();
319
320         glEnable(GL_CULL_FACE);
321         glEnable(GL_DEPTH_TEST);
322         glClearDepth(1.0); 
323         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
324         glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
325         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
326         glDepthMask (GL_TRUE);
327         glDepthFunc(GL_LEQUAL);
328         glBlendFunc(GL_ONE, GL_ZERO);
329         
330         glDisable(GL_POLYGON_STIPPLE);
331         
332         glDisable(GL_LIGHTING);
333         if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
334                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
335         
336         EndFrame();
337 }
338
339 bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
340 {
341         m_time = time;
342         SetDrawingMode(drawingmode);
343
344         // Blender camera routine destroys the settings
345         if (m_drawingmode < KX_SOLID)
346         {
347                 glDisable(GL_CULL_FACE);
348                 glDisable(GL_DEPTH_TEST);
349         }
350         else
351         {
352                 glEnable(GL_DEPTH_TEST);
353                 glEnable(GL_CULL_FACE);
354         }
355
356         glDisable(GL_BLEND);
357         glDisable(GL_ALPHA_TEST);
358         //m_last_alphablend = GPU_BLEND_SOLID;
359         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
360
361         glFrontFace(GL_CCW);
362         m_last_frontface = true;
363
364         glShadeModel(GL_SMOOTH);
365
366         glEnable(GL_MULTISAMPLE_ARB);
367
368         m_2DCanvas->BeginFrame();
369
370         // Render Tools
371         m_clientobject = NULL;
372         m_lastlightlayer = -1;
373         m_lastauxinfo = NULL;
374         m_lastlighting = true; /* force disable in DisableOpenGLLights() */
375         DisableOpenGLLights();
376         
377         return true;
378 }
379
380
381
382 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
383 {
384         m_drawingmode = drawingmode;
385
386         if (m_drawingmode == KX_WIREFRAME)
387                 glDisable(GL_CULL_FACE);
388
389         m_storage->SetDrawingMode(drawingmode);
390         if (m_failsafe_storage && m_failsafe_storage != m_storage) {
391                 m_failsafe_storage->SetDrawingMode(drawingmode);
392         }
393 }
394
395 int RAS_OpenGLRasterizer::GetDrawingMode()
396 {
397         return m_drawingmode;
398 }
399
400
401 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
402 {
403         glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
404 }
405
406
407 void RAS_OpenGLRasterizer::ClearColorBuffer()
408 {
409         m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
410         m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
411 }
412
413
414 void RAS_OpenGLRasterizer::ClearDepthBuffer()
415 {
416         m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
417 }
418
419
420 void RAS_OpenGLRasterizer::ClearCachingInfo(void)
421 {
422         m_materialCachingInfo = 0;
423 }
424
425 void RAS_OpenGLRasterizer::FlushDebugShapes()
426 {
427         if (m_debugShapes.empty())
428                 return;
429
430         // DrawDebugLines
431         GLboolean light, tex;
432
433         light= glIsEnabled(GL_LIGHTING);
434         tex= glIsEnabled(GL_TEXTURE_2D);
435
436         if (light) glDisable(GL_LIGHTING);
437         if (tex) glDisable(GL_TEXTURE_2D);
438
439         //draw lines
440         glBegin(GL_LINES);
441         for (unsigned int i=0;i<m_debugShapes.size();i++)
442         {
443                 if (m_debugShapes[i].m_type != OglDebugShape::LINE)
444                         continue;
445                 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
446                 const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x();
447                 const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x();
448                 glVertex3dv(fromPtr);
449                 glVertex3dv(toPtr);
450         }
451         glEnd();
452
453         //draw circles
454         for (unsigned int i=0;i<m_debugShapes.size();i++)
455         {
456                 if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE)
457                         continue;
458                 glBegin(GL_LINE_LOOP);
459                 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
460
461                 static const MT_Vector3 worldUp(0.0, 0.0, 1.0);
462                 MT_Vector3 norm = m_debugShapes[i].m_param;
463                 MT_Matrix3x3 tr;
464                 if (norm.fuzzyZero() || norm == worldUp)
465                 {
466                         tr.setIdentity();
467                 }
468                 else
469                 {
470                         MT_Vector3 xaxis, yaxis;
471                         xaxis = MT_cross(norm, worldUp);
472                         yaxis = MT_cross(xaxis, norm);
473                         tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(),
474                                 yaxis.x(), yaxis.y(), yaxis.z(),
475                                 norm.x(), norm.y(), norm.z());
476                 }
477                 MT_Scalar rad = m_debugShapes[i].m_param2.x();
478                 int n = (int) m_debugShapes[i].m_param2.y();
479                 for (int j = 0; j<n; j++)
480                 {
481                         MT_Scalar theta = j*M_PI*2/n;
482                         MT_Vector3 pos(cos(theta) * rad, sin(theta) * rad, 0.0);
483                         pos = pos*tr;
484                         pos += m_debugShapes[i].m_pos;
485                         const MT_Scalar* posPtr = &pos.x();
486                         glVertex3dv(posPtr);
487                 }
488                 glEnd();
489         }
490
491         if (light) glEnable(GL_LIGHTING);
492         if (tex) glEnable(GL_TEXTURE_2D);
493
494         m_debugShapes.clear();
495 }
496
497 void RAS_OpenGLRasterizer::EndFrame()
498 {
499         FlushDebugShapes();
500
501         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
502
503         glDisable(GL_MULTISAMPLE_ARB);
504
505         m_2DCanvas->EndFrame();
506 }
507
508 void RAS_OpenGLRasterizer::SetRenderArea()
509 {
510         RAS_Rect area;
511         // only above/below stereo method needs viewport adjustment
512         switch (m_stereomode)
513         {
514                 case RAS_STEREO_ABOVEBELOW:
515                         switch (m_curreye) {
516                                 case RAS_STEREO_LEFTEYE:
517                                         // upper half of window
518                                         area.SetLeft(0);
519                                         area.SetBottom(m_2DCanvas->GetHeight() -
520                                                 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
521         
522                                         area.SetRight(int(m_2DCanvas->GetWidth()));
523                                         area.SetTop(int(m_2DCanvas->GetHeight()));
524                                         m_2DCanvas->SetDisplayArea(&area);
525                                         break;
526                                 case RAS_STEREO_RIGHTEYE:
527                                         // lower half of window
528                                         area.SetLeft(0);
529                                         area.SetBottom(0);
530                                         area.SetRight(int(m_2DCanvas->GetWidth()));
531                                         area.SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
532                                         m_2DCanvas->SetDisplayArea(&area);
533                                         break;
534                         }
535                         break;
536                 case RAS_STEREO_SIDEBYSIDE:
537                         switch (m_curreye)
538                         {
539                                 case RAS_STEREO_LEFTEYE:
540                                         // Left half of window
541                                         area.SetLeft(0);
542                                         area.SetBottom(0);
543                                         area.SetRight(m_2DCanvas->GetWidth()/2);
544                                         area.SetTop(m_2DCanvas->GetHeight());
545                                         m_2DCanvas->SetDisplayArea(&area);
546                                         break;
547                                 case RAS_STEREO_RIGHTEYE:
548                                         // Right half of window
549                                         area.SetLeft(m_2DCanvas->GetWidth()/2);
550                                         area.SetBottom(0);
551                                         area.SetRight(m_2DCanvas->GetWidth());
552                                         area.SetTop(m_2DCanvas->GetHeight());
553                                         m_2DCanvas->SetDisplayArea(&area);
554                                         break;
555                         }
556                         break;
557                 default:
558                         // every available pixel
559                         area.SetLeft(0);
560                         area.SetBottom(0);
561                         area.SetRight(int(m_2DCanvas->GetWidth()));
562                         area.SetTop(int(m_2DCanvas->GetHeight()));
563                         m_2DCanvas->SetDisplayArea(&area);
564                         break;
565         }
566 }
567         
568 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
569 {
570         m_stereomode = stereomode;
571 }
572
573 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
574 {
575         return m_stereomode;
576 }
577
578 bool RAS_OpenGLRasterizer::Stereo()
579 {
580         if (m_stereomode > RAS_STEREO_NOSTEREO) // > 0
581                 return true;
582         else
583                 return false;
584 }
585
586 bool RAS_OpenGLRasterizer::InterlacedStereo()
587 {
588         return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
589 }
590
591 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
592 {
593         m_curreye = eye;
594         switch (m_stereomode)
595         {
596                 case RAS_STEREO_QUADBUFFERED:
597                         glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
598                         break;
599                 case RAS_STEREO_ANAGLYPH:
600                         if (m_curreye == RAS_STEREO_LEFTEYE) {
601                                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
602                         }
603                         else {
604                                 //glAccum(GL_LOAD, 1.0);
605                                 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
606                                 ClearDepthBuffer();
607                         }
608                         break;
609                 case RAS_STEREO_VINTERLACE:
610                 {
611                         glEnable(GL_POLYGON_STIPPLE);
612                         glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
613                         if (m_curreye == RAS_STEREO_RIGHTEYE)
614                                 ClearDepthBuffer();
615                         break;
616                 }
617                 case RAS_STEREO_INTERLACED:
618                 {
619                         glEnable(GL_POLYGON_STIPPLE);
620                         glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
621                         if (m_curreye == RAS_STEREO_RIGHTEYE)
622                                 ClearDepthBuffer();
623                         break;
624                 }
625                 default:
626                         break;
627         }
628 }
629
630 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
631 {
632         return m_curreye;
633 }
634
635
636 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
637 {
638         m_eyeseparation = eyeseparation;
639 }
640
641 float RAS_OpenGLRasterizer::GetEyeSeparation()
642 {
643         return m_eyeseparation;
644 }
645
646 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
647 {
648         m_focallength = focallength;
649         m_setfocallength = true;
650 }
651
652 float RAS_OpenGLRasterizer::GetFocalLength()
653 {
654         return m_focallength;
655 }
656
657
658 void RAS_OpenGLRasterizer::SwapBuffers()
659 {
660         m_2DCanvas->SwapBuffers();
661 }
662
663
664
665 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
666 {
667         return m_viewmatrix;
668 }
669
670 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
671 {
672         return m_viewinvmatrix;
673 }
674
675 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
676                                                                         class RAS_IPolyMaterial* polymat)
677
678         bool obcolor = ms.m_bObjectColor;
679         MT_Vector4& rgba = ms.m_RGBAcolor;
680         RAS_MeshSlot::iterator it;
681
682         const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
683
684         // handle object color
685         if (obcolor) {
686                 glDisableClientState(GL_COLOR_ARRAY);
687                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
688         }
689         else
690                 glEnableClientState(GL_COLOR_ARRAY);
691
692         for (ms.begin(it); !ms.end(it); ms.next(it)) {
693                 RAS_TexVert *vertex;
694                 size_t i, j, numvert;
695                 
696                 numvert = it.array->m_type;
697
698                 if (it.array->m_type == RAS_DisplayArray::LINE) {
699                         // line drawing, no text
700                         glBegin(GL_LINES);
701
702                         for (i=0; i<it.totindex; i+=2)
703                         {
704                                 vertex = &it.vertex[it.index[i]];
705                                 glVertex3fv(vertex->getXYZ());
706
707                                 vertex = &it.vertex[it.index[i+1]];
708                                 glVertex3fv(vertex->getXYZ());
709                         }
710
711                         glEnd();
712                 }
713                 else {
714                         // triangle and quad text drawing
715                         for (i=0; i<it.totindex; i+=numvert)
716                         {
717                                 float v[4][3];
718                                 int glattrib, unit;
719
720                                 for (j=0; j<numvert; j++) {
721                                         vertex = &it.vertex[it.index[i+j]];
722
723                                         v[j][0] = vertex->getXYZ()[0];
724                                         v[j][1] = vertex->getXYZ()[1];
725                                         v[j][2] = vertex->getXYZ()[2];
726                                 }
727
728                                 // find the right opengl attribute
729                                 glattrib = -1;
730                                 if (GLEW_ARB_vertex_program)
731                                         for (unit=0; unit<m_attrib_num; unit++)
732                                                 if (m_attrib[unit] == RAS_TEXCO_UV)
733                                                         glattrib = unit;
734
735                                 GPU_render_text(polymat->GetMTFace(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(), v[1], v[2], v[3], v[4], glattrib);
736
737                                 ClearCachingInfo();
738                         }
739                 }
740         }
741
742         glDisableClientState(GL_COLOR_ARRAY);
743 }
744
745 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
746 {
747         m_texco_num = num;
748         if (m_texco_num > RAS_MAX_TEXCO)
749                 m_texco_num = RAS_MAX_TEXCO;
750 }
751
752 void RAS_OpenGLRasterizer::SetAttribNum(int num)
753 {
754         m_attrib_num = num;
755         if (m_attrib_num > RAS_MAX_ATTRIB)
756                 m_attrib_num = RAS_MAX_ATTRIB;
757 }
758
759 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
760 {
761         // this changes from material to material
762         if (unit < RAS_MAX_TEXCO)
763                 m_texco[unit] = coords;
764 }
765
766 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit, int layer)
767 {
768         // this changes from material to material
769         if (unit < RAS_MAX_ATTRIB) {
770                 m_attrib[unit] = coords;
771                 m_attrib_layer[unit] = layer;
772         }
773 }
774
775 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
776 {
777         if (ms.m_pDerivedMesh)
778                 m_failsafe_storage->IndexPrimitives(ms);
779         else
780                 m_storage->IndexPrimitives(ms);
781 }
782
783 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
784 {
785         if (ms.m_pDerivedMesh)
786                 m_failsafe_storage->IndexPrimitivesMulti(ms);
787         else
788                 m_storage->IndexPrimitivesMulti(ms);
789 }
790
791 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
792 {
793         glMatrixMode(GL_PROJECTION);
794         double* matrix = &mat(0, 0);
795         glLoadMatrixd(matrix);
796
797         m_camortho = (mat(3, 3) != 0.0);
798 }
799
800 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
801 {
802         glMatrixMode(GL_PROJECTION);
803         double matrix[16];
804         /* Get into argument. Looks a bit dodgy, but it's ok. */
805         mat.getValue(matrix);
806         /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
807         glLoadMatrixd(matrix);
808
809         m_camortho= (mat[3][3] != 0.0);
810 }
811
812 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
813         float left,
814         float right,
815         float bottom,
816         float top,
817         float frustnear,
818         float frustfar,
819         float focallength,
820         bool 
821 ) {
822         MT_Matrix4x4 result;
823         double mat[16];
824
825         // correction for stereo
826         if (Stereo())
827         {
828                         float near_div_focallength;
829                         float offset;
830
831                         // if Rasterizer.setFocalLength is not called we use the camera focallength
832                         if (!m_setfocallength)
833                                 // if focallength is null we use a value known to be reasonable
834                                 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0f
835                                         : focallength;
836
837                         near_div_focallength = frustnear / m_focallength;
838                         offset = 0.5f * m_eyeseparation * near_div_focallength;
839                         switch (m_curreye) {
840                                 case RAS_STEREO_LEFTEYE:
841                                                 left += offset;
842                                                 right += offset;
843                                                 break;
844                                 case RAS_STEREO_RIGHTEYE:
845                                                 left -= offset;
846                                                 right -= offset;
847                                                 break;
848                         }
849                         // leave bottom and top untouched
850         }
851         
852         glMatrixMode(GL_PROJECTION);
853         glLoadIdentity();
854         glFrustum(left, right, bottom, top, frustnear, frustfar);
855                 
856         glGetDoublev(GL_PROJECTION_MATRIX, mat);
857         result.setValue(mat);
858
859         return result;
860 }
861
862 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
863         float left,
864         float right,
865         float bottom,
866         float top,
867         float frustnear,
868         float frustfar
869 ) {
870         MT_Matrix4x4 result;
871         double mat[16];
872
873         // stereo is meaning less for orthographic, disable it
874         glMatrixMode(GL_PROJECTION);
875         glLoadIdentity();
876         glOrtho(left, right, bottom, top, frustnear, frustfar);
877                 
878         glGetDoublev(GL_PROJECTION_MATRIX, mat);
879         result.setValue(mat);
880
881         return result;
882 }
883
884
885 // next arguments probably contain redundant info, for later...
886 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, 
887                                                                                  const MT_Matrix3x3 & camOrientMat3x3,
888                                                                                  const MT_Point3 & pos,
889                                                                                  bool perspective)
890 {
891         m_viewmatrix = mat;
892
893         // correction for stereo
894         if (Stereo() && perspective)
895         {
896                 MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
897                 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
898                 MT_Vector3 viewDir, viewupVec;
899                 MT_Vector3 eyeline;
900
901                 // actual viewDir
902                 viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
903                 // actual viewup vec
904                 viewupVec = camOrientMat3x3 * unitViewupVec;
905
906                 // vector between eyes
907                 eyeline = viewDir.cross(viewupVec);
908
909                 switch (m_curreye) {
910                         case RAS_STEREO_LEFTEYE:
911                                 {
912                                 // translate to left by half the eye distance
913                                 MT_Transform transform;
914                                 transform.setIdentity();
915                                 transform.translate(-(eyeline * m_eyeseparation / 2.0));
916                                 m_viewmatrix *= transform;
917                                 }
918                                 break;
919                         case RAS_STEREO_RIGHTEYE:
920                                 {
921                                 // translate to right by half the eye distance
922                                 MT_Transform transform;
923                                 transform.setIdentity();
924                                 transform.translate(eyeline * m_eyeseparation / 2.0);
925                                 m_viewmatrix *= transform;
926                                 }
927                                 break;
928                 }
929         }
930
931         m_viewinvmatrix = m_viewmatrix;
932         m_viewinvmatrix.invert();
933
934         // note: getValue gives back column major as needed by OpenGL
935         MT_Scalar glviewmat[16];
936         m_viewmatrix.getValue(glviewmat);
937
938         glMatrixMode(GL_MODELVIEW);
939         glLoadMatrixd(glviewmat);
940         m_campos = pos;
941 }
942
943
944 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
945 {
946         return m_campos;
947 }
948
949 bool RAS_OpenGLRasterizer::GetCameraOrtho()
950 {
951         return m_camortho;
952 }
953
954 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
955 {
956         if (enable)
957                 glEnable(GL_CULL_FACE);
958         else
959                 glDisable(GL_CULL_FACE);
960 }
961
962 void RAS_OpenGLRasterizer::SetLines(bool enable)
963 {
964         if (enable)
965                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
966         else
967                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
968 }
969
970 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
971                                                                                   float specY,
972                                                                                   float specZ,
973                                                                                   float specval)
974 {
975         GLfloat mat_specular[] = {specX, specY, specZ, specval};
976         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
977 }
978
979
980
981 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
982 {
983         GLfloat mat_shininess[] = {     shiny };
984         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
985 }
986
987
988
989 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
990 {
991         GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
992         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
993 }
994
995 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
996 {
997         GLfloat mat_emit [] = {eX,eY,eZ,e};
998         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
999 }
1000
1001
1002 double RAS_OpenGLRasterizer::GetTime()
1003 {
1004         return m_time;
1005 }
1006
1007 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
1008 {
1009         glPolygonOffset(mult, add);
1010         GLint mode = GL_POLYGON_OFFSET_FILL;
1011         if (m_drawingmode < KX_SHADED)
1012                 mode = GL_POLYGON_OFFSET_LINE;
1013         if (mult != 0.0f || add != 0.0f)
1014                 glEnable(mode);
1015         else
1016                 glDisable(mode);
1017 }
1018
1019 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
1020 {
1021         /* don't just set m_motionblur to 1, but check if it is 0 so
1022          * we don't reset a motion blur that is already enabled */
1023         if (m_motionblur == 0)
1024                 m_motionblur = 1;
1025         m_motionblurvalue = motionblurvalue;
1026 }
1027
1028 void RAS_OpenGLRasterizer::DisableMotionBlur()
1029 {
1030         m_motionblur = 0;
1031         m_motionblurvalue = -1.0;
1032 }
1033
1034 void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend)
1035 {
1036         /* Variance shadow maps don't handle alpha well, best to not allow it for now  */
1037         if (m_drawingmode == KX_SHADOW && m_usingoverrideshader)
1038                 GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
1039         else
1040                 GPU_set_material_alpha_blend(alphablend);
1041 /*
1042         if (alphablend == m_last_alphablend)
1043                 return;
1044
1045         if (alphablend == GPU_BLEND_SOLID) {
1046                 glDisable(GL_BLEND);
1047                 glDisable(GL_ALPHA_TEST);
1048                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1049         }
1050         else if (alphablend == GPU_BLEND_ADD) {
1051                 glBlendFunc(GL_ONE, GL_ONE);
1052                 glEnable(GL_BLEND);
1053                 glDisable(GL_ALPHA_TEST);
1054         }
1055         else if (alphablend == GPU_BLEND_ALPHA) {
1056                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1057                 glEnable(GL_BLEND);
1058                 glEnable(GL_ALPHA_TEST);
1059                 glAlphaFunc(GL_GREATER, 0.0f);
1060         }
1061         else if (alphablend == GPU_BLEND_CLIP) {
1062                 glDisable(GL_BLEND); 
1063                 glEnable(GL_ALPHA_TEST);
1064                 glAlphaFunc(GL_GREATER, 0.5f);
1065         }
1066
1067         m_last_alphablend = alphablend;
1068 */
1069 }
1070
1071 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
1072 {
1073         if (m_last_frontface == ccw)
1074                 return;
1075
1076         if (ccw)
1077                 glFrontFace(GL_CCW);
1078         else
1079                 glFrontFace(GL_CW);
1080         
1081         m_last_frontface = ccw;
1082 }
1083
1084 void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level)
1085 {
1086         GPU_set_anisotropic((float)level);
1087 }
1088
1089 short RAS_OpenGLRasterizer::GetAnisotropicFiltering()
1090 {
1091         return (short)GPU_get_anisotropic();
1092 }
1093
1094 void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val)
1095 {
1096         if (val == RAS_IRasterizer::RAS_MIPMAP_LINEAR)
1097         {
1098                 GPU_set_linear_mipmap(1);
1099                 GPU_set_mipmap(1);
1100         }
1101         else if (val == RAS_IRasterizer::RAS_MIPMAP_NEAREST)
1102         {
1103                 GPU_set_linear_mipmap(0);
1104                 GPU_set_mipmap(1);
1105         }
1106         else
1107         {
1108                 GPU_set_linear_mipmap(0);
1109                 GPU_set_mipmap(0);
1110         }
1111 }
1112
1113 RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping()
1114 {
1115         if (GPU_get_linear_mipmap())
1116                 return RAS_IRasterizer::RAS_MIPMAP_LINEAR;
1117         else if (GPU_get_mipmap())
1118                 return RAS_IRasterizer::RAS_MIPMAP_NEAREST;
1119         else
1120                 return RAS_IRasterizer::RAS_MIPMAP_NONE;
1121 }
1122
1123 void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val)
1124 {
1125         m_usingoverrideshader = val;
1126 }
1127
1128 bool RAS_OpenGLRasterizer::GetUsingOverrideShader()
1129 {
1130         return m_usingoverrideshader;
1131 }
1132
1133 /**
1134  * Render Tools
1135  */
1136
1137 /* ProcessLighting performs lighting on objects. the layer is a bitfield that
1138  * contains layer information. There are 20 'official' layers in blender. A
1139  * light is applied on an object only when they are in the same layer. OpenGL
1140  * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in
1141  * a scene. */
1142
1143 void RAS_OpenGLRasterizer::ProcessLighting(bool uselights, const MT_Transform& viewmat)
1144 {
1145         bool enable = false;
1146         int layer= -1;
1147
1148         /* find the layer */
1149         if (uselights) {
1150                 if (m_clientobject)
1151                         layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer();
1152         }
1153
1154         /* avoid state switching */
1155         if (m_lastlightlayer == layer && m_lastauxinfo == m_auxilaryClientInfo)
1156                 return;
1157
1158         m_lastlightlayer = layer;
1159         m_lastauxinfo = m_auxilaryClientInfo;
1160
1161         /* enable/disable lights as needed */
1162         if (layer >= 0)
1163                 enable = ApplyLights(layer, viewmat);
1164
1165         if (enable)
1166                 EnableOpenGLLights();
1167         else
1168                 DisableOpenGLLights();
1169 }
1170
1171 void RAS_OpenGLRasterizer::EnableOpenGLLights()
1172 {
1173         if (m_lastlighting == true)
1174                 return;
1175
1176         glEnable(GL_LIGHTING);
1177         glEnable(GL_COLOR_MATERIAL);
1178
1179         glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1180         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
1181         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (GetCameraOrtho())? GL_FALSE: GL_TRUE);
1182         if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
1183                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1184
1185         m_lastlighting = true;
1186 }
1187
1188 void RAS_OpenGLRasterizer::DisableOpenGLLights()
1189 {
1190         if (m_lastlighting == false)
1191                 return;
1192
1193         glDisable(GL_LIGHTING);
1194         glDisable(GL_COLOR_MATERIAL);
1195
1196         m_lastlighting = false;
1197 }
1198
1199 void RAS_OpenGLRasterizer::AddLight(struct RAS_LightObject* lightobject)
1200 {
1201         m_lights.push_back(lightobject);
1202 }
1203
1204 void RAS_OpenGLRasterizer::RemoveLight(struct RAS_LightObject* lightobject)
1205 {
1206         std::vector<struct      RAS_LightObject*>::iterator lit =
1207                 std::find(m_lights.begin(),m_lights.end(),lightobject);
1208
1209         if (!(lit==m_lights.end()))
1210                 m_lights.erase(lit);
1211 }
1212
1213 bool RAS_OpenGLRasterizer::RayHit(class KX_ClientObjectInfo *client, KX_RayCast *result, void * const data)
1214 {
1215         double* const oglmatrix = (double* const) data;
1216
1217         RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon);
1218         if (!poly->IsVisible())
1219                 return false;
1220
1221         MT_Point3 resultpoint(result->m_hitPoint);
1222         MT_Vector3 resultnormal(result->m_hitNormal);
1223         MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
1224         MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
1225         left = (dir.cross(resultnormal)).safe_normalized();
1226         // for the up vector, we take the 'resultnormal' returned by the physics
1227
1228         double maat[16] = {left[0],         left[1],         left[2],         0,
1229                            dir[0],          dir[1],          dir[2],          0,
1230                            resultnormal[0], resultnormal[1], resultnormal[2], 0,
1231                            0,               0,               0,               1};
1232
1233         glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
1234         //glMultMatrixd(oglmatrix);
1235         glMultMatrixd(maat);
1236         return true;
1237 }
1238
1239 void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode )
1240 {
1241         /* FIXME:
1242         blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const
1243         MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed.
1244
1245         Program received signal SIGABRT, Aborted.
1246         [Switching to Thread 16384 (LWP 1519)]
1247         0x40477571 in kill () from /lib/libc.so.6
1248         (gdb) bt
1249         #7  0x08334368 in MT_Vector3::normalized() const ()
1250         #8  0x0833e6ec in RAS_OpenGLRasterizer::applyTransform(RAS_IRasterizer*, double*, int) ()
1251         */
1252
1253         if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
1254                 objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
1255         {
1256                 // rotate the billboard/halo
1257                 //page 360/361 3D Game Engine Design, David Eberly for a discussion
1258                 // on screen aligned and axis aligned billboards
1259                 // assumed is that the preprocessor transformed all billboard polygons
1260                 // so that their normal points into the positive x direction (1.0, 0.0, 0.0)
1261                 // when new parenting for objects is done, this rotation
1262                 // will be moved into the object
1263
1264                 MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1265                 MT_Point3 campos = GetCameraPosition();
1266                 MT_Vector3 dir = (campos - objpos).safe_normalized();
1267                 MT_Vector3 up(0,0,1.0);
1268
1269                 KX_GameObject* gameobj = (KX_GameObject*)m_clientobject;
1270                 // get scaling of halo object
1271                 MT_Vector3  size = gameobj->GetSGNode()->GetWorldScaling();
1272
1273                 bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
1274                 if (screenaligned)
1275                 {
1276                         up = (up - up.dot(dir) * dir).safe_normalized();
1277                 } else
1278                 {
1279                         dir = (dir - up.dot(dir)*up).safe_normalized();
1280                 }
1281
1282                 MT_Vector3 left = dir.normalized();
1283                 dir = (up.cross(left)).normalized();
1284
1285                 // we have calculated the row vectors, now we keep
1286                 // local scaling into account:
1287
1288                 left *= size[0];
1289                 dir  *= size[1];
1290                 up   *= size[2];
1291
1292                 double maat[16] = {left[0], left[1], left[2], 0,
1293                                    dir[0],  dir[1],  dir[2],  0,
1294                                    up[0],   up[1],   up[2],   0,
1295                                    0,       0,       0,       1};
1296
1297                 glTranslated(objpos[0],objpos[1],objpos[2]);
1298                 glMultMatrixd(maat);
1299
1300         }
1301         else {
1302                 if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
1303                 {
1304                         // shadow must be cast to the ground, physics system needed here!
1305                         MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1306                         KX_GameObject *gameobj = (KX_GameObject*)m_clientobject;
1307                         MT_Vector3 direction = MT_Vector3(0,0,-1);
1308
1309                         direction.normalize();
1310                         direction *= 100000;
1311
1312                         MT_Point3 topoint = frompoint + direction;
1313
1314                         KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo;
1315                         PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment();
1316                         KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController();
1317
1318                         KX_GameObject *parent = gameobj->GetParent();
1319                         if (!physics_controller && parent)
1320                                 physics_controller = parent->GetPhysicsController();
1321                         if (parent)
1322                                 parent->Release();
1323
1324                         KX_RayCast::Callback<RAS_OpenGLRasterizer> callback(this, physics_controller, oglmatrix);
1325                         if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
1326                         {
1327                                 // couldn't find something to cast the shadow on...
1328                                 glMultMatrixd(oglmatrix);
1329                         }
1330                         else
1331                         { // we found the "ground", but the cast matrix doesn't take
1332                           // scaling in consideration, so we must apply the object scale
1333                                 MT_Vector3  size = gameobj->GetSGNode()->GetLocalScale();
1334                                 glScalef(size[0], size[1], size[2]);
1335                         }
1336                 } else
1337                 {
1338
1339                         // 'normal' object
1340                         glMultMatrixd(oglmatrix);
1341                 }
1342         }
1343 }
1344
1345 static void DisableForText()
1346 {
1347         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */
1348
1349         glDisable(GL_BLEND);
1350         glDisable(GL_ALPHA_TEST);
1351
1352         glDisable(GL_LIGHTING);
1353         glDisable(GL_COLOR_MATERIAL);
1354
1355         if (GLEW_ARB_multitexture) {
1356                 for (int i=0; i<RAS_MAX_TEXCO; i++) {
1357                         glActiveTextureARB(GL_TEXTURE0_ARB+i);
1358
1359                         if (GLEW_ARB_texture_cube_map)
1360                                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1361
1362                         glDisable(GL_TEXTURE_2D);
1363                 }
1364
1365                 glActiveTextureARB(GL_TEXTURE0_ARB);
1366         }
1367         else {
1368                 if (GLEW_ARB_texture_cube_map)
1369                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1370
1371                 glDisable(GL_TEXTURE_2D);
1372         }
1373 }
1374
1375 void RAS_OpenGLRasterizer::RenderBox2D(int xco,
1376                         int yco,
1377                         int width,
1378                         int height,
1379                         float percentage)
1380 {
1381         /* This is a rather important line :( The gl-mode hasn't been left
1382          * behind quite as neatly as we'd have wanted to. I don't know
1383          * what cause it, though :/ .*/
1384         glDisable(GL_DEPTH_TEST);
1385
1386         glMatrixMode(GL_PROJECTION);
1387         glPushMatrix();
1388         glLoadIdentity();
1389
1390         glOrtho(0, width, 0, height, -100, 100);
1391
1392         glMatrixMode(GL_MODELVIEW);
1393         glPushMatrix();
1394         glLoadIdentity();
1395
1396         yco = height - yco;
1397         int barsize = 50;
1398
1399         /* draw in black first*/
1400         glColor3ub(0, 0, 0);
1401         glBegin(GL_QUADS);
1402         glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1 + 10);
1403         glVertex2f(xco + 1, yco - 1 + 10);
1404         glVertex2f(xco + 1, yco - 1);
1405         glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1);
1406         glEnd();
1407
1408         glColor3ub(255, 255, 255);
1409         glBegin(GL_QUADS);
1410         glVertex2f(xco + 1 + barsize * percentage, yco + 10);
1411         glVertex2f(xco, yco + 10);
1412         glVertex2f(xco, yco);
1413         glVertex2f(xco + 1 + barsize * percentage, yco);
1414         glEnd();
1415
1416         glMatrixMode(GL_PROJECTION);
1417         glPopMatrix();
1418         glMatrixMode(GL_MODELVIEW);
1419         glPopMatrix();
1420         glEnable(GL_DEPTH_TEST);
1421 }
1422
1423 void RAS_OpenGLRasterizer::RenderText3D(int fontid,
1424                                                                                  const char* text,
1425                                                                                  int size,
1426                                                                                  int dpi,
1427                                                                                  float* color,
1428                                                                                  double* mat,
1429                                                                                  float aspect)
1430 {
1431         /* gl prepping */
1432         DisableForText();
1433
1434         /* the actual drawing */
1435         glColor4fv(color);
1436
1437         /* multiply the text matrix by the object matrix */
1438         BLF_enable(fontid, BLF_MATRIX|BLF_ASPECT);
1439         BLF_matrix(fontid, mat);
1440
1441         /* aspect is the inverse scale that allows you to increase */
1442         /* your resolution without sizing the final text size      */
1443         /* the bigger the size, the smaller the aspect             */
1444         BLF_aspect(fontid, aspect, aspect, aspect);
1445
1446         BLF_size(fontid, size, dpi);
1447         BLF_position(fontid, 0, 0, 0);
1448         BLF_draw(fontid, (char *)text, 65535);
1449
1450         BLF_disable(fontid, BLF_MATRIX|BLF_ASPECT);
1451 }
1452
1453 void RAS_OpenGLRasterizer::RenderText2D(RAS_TEXT_RENDER_MODE mode,
1454                                                                                  const char* text,
1455                                                                                  int xco,
1456                                                                                  int yco,
1457                                                                                  int width,
1458                                                                                  int height)
1459 {
1460         /* This is a rather important line :( The gl-mode hasn't been left
1461          * behind quite as neatly as we'd have wanted to. I don't know
1462          * what cause it, though :/ .*/
1463         DisableForText();
1464         glDisable(GL_DEPTH_TEST);
1465
1466         glMatrixMode(GL_PROJECTION);
1467         glPushMatrix();
1468         glLoadIdentity();
1469
1470         glOrtho(0, width, 0, height, -100, 100);
1471
1472         glMatrixMode(GL_MODELVIEW);
1473         glPushMatrix();
1474         glLoadIdentity();
1475
1476         if (mode == RAS_TEXT_PADDED) {
1477                 /* draw in black first*/
1478                 glColor3ub(0, 0, 0);
1479                 BLF_size(blf_mono_font, 11, 72);
1480                 BLF_position(blf_mono_font, (float)xco+1, (float)(height-yco-1), 0.0f);
1481                 BLF_draw(blf_mono_font, (char *)text, 65535);/* XXX, use real len */
1482
1483                 glColor3ub(255, 255, 255);
1484                 BLF_position(blf_mono_font, (float)xco, (float)(height-yco), 0.0f);
1485                 BLF_draw(blf_mono_font, (char *)text, 65535);
1486         } else {
1487                 /* the actual drawing */
1488                 glColor3ub(255, 255, 255);
1489                 BLF_size(blf_mono_font, 11, 72);
1490                 BLF_position(blf_mono_font, (float)xco, (float)(height-yco), 0.0f);
1491                 BLF_draw(blf_mono_font, (char *)text, 65535); /* XXX, use real len */
1492         }
1493
1494         glMatrixMode(GL_PROJECTION);
1495         glPopMatrix();
1496         glMatrixMode(GL_MODELVIEW);
1497         glPopMatrix();
1498         glEnable(GL_DEPTH_TEST);
1499 }
1500
1501 void RAS_OpenGLRasterizer::PushMatrix()
1502 {
1503         glPushMatrix();
1504 }
1505
1506 void RAS_OpenGLRasterizer::PopMatrix()
1507 {
1508         glPopMatrix();
1509 }
1510
1511
1512 int RAS_OpenGLRasterizer::ApplyLights(int objectlayer, const MT_Transform& viewmat)
1513 {
1514         // taken from blender source, incompatibility between Blender Object / GameObject
1515         KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo;
1516         float glviewmat[16];
1517         unsigned int count;
1518         std::vector<struct      RAS_LightObject*>::iterator lit = m_lights.begin();
1519
1520         for (count=0; count<m_numgllights; count++)
1521                 glDisable((GLenum)(GL_LIGHT0+count));
1522
1523         viewmat.getValue(glviewmat);
1524
1525         glPushMatrix();
1526         glLoadMatrixf(glviewmat);
1527         for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit)
1528         {
1529                 RAS_LightObject* lightdata = (*lit);
1530                 KX_LightObject *kxlight = (KX_LightObject*)lightdata->m_light;
1531
1532                 if (kxlight->ApplyLight(kxscene, objectlayer, count))
1533                         count++;
1534         }
1535         glPopMatrix();
1536
1537         return count;
1538 }
1539
1540 void RAS_OpenGLRasterizer::MotionBlur()
1541 {
1542         int state = GetMotionBlurState();
1543         float motionblurvalue;
1544         if (state)
1545         {
1546                 motionblurvalue = GetMotionBlurValue();
1547                 if (state==1)
1548                 {
1549                         //bugfix:load color buffer into accum buffer for the first time(state=1)
1550                         glAccum(GL_LOAD, 1.0);
1551                         SetMotionBlurState(2);
1552                 }
1553                 else if (motionblurvalue >= 0.0f && motionblurvalue <= 1.0f) {
1554                         glAccum(GL_MULT, motionblurvalue);
1555                         glAccum(GL_ACCUM, 1-motionblurvalue);
1556                         glAccum(GL_RETURN, 1.0);
1557                         glFlush();
1558                 }
1559         }
1560 }
1561
1562 void RAS_OpenGLRasterizer::SetClientObject(void* obj)
1563 {
1564         if (m_clientobject != obj)
1565         {
1566                 bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling());
1567                 SetFrontFace(ccw);
1568
1569                 m_clientobject = obj;
1570         }
1571 }
1572
1573 void RAS_OpenGLRasterizer::SetAuxilaryClientInfo(void* inf)
1574 {
1575         m_auxilaryClientInfo = inf;
1576 }
1577