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