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