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