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