Various game engine fixes:
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_OpenGLRasterizer.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28  
29 #include <math.h>
30 #include <stdlib.h>
31  
32 #include "RAS_OpenGLRasterizer.h"
33
34 #include "GL/glew.h"
35
36 #include "RAS_Rect.h"
37 #include "RAS_TexVert.h"
38 #include "MT_CmMatrix4x4.h"
39 #include "RAS_IRenderTools.h" // rendering text
40
41 #include "GPU_draw.h"
42 #include "GPU_material.h"
43
44 /**
45  *  32x32 bit masks for vinterlace stereo mode
46  */
47 static GLuint left_eye_vinterlace_mask[32];
48 static GLuint right_eye_vinterlace_mask[32];
49
50 /**
51  *  32x32 bit masks for hinterlace stereo mode.
52  *  Left eye = &hinterlace_mask[0]
53  *  Right eye = &hinterlace_mask[1]
54  */
55 static GLuint hinterlace_mask[33];
56
57 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
58         :RAS_IRasterizer(canvas),
59         m_2DCanvas(canvas),
60         m_fogenabled(false),
61         m_time(0.0),
62         m_stereomode(RAS_STEREO_NOSTEREO),
63         m_curreye(RAS_STEREO_LEFTEYE),
64         m_eyeseparation(0.0),
65         m_seteyesep(false),
66         m_focallength(0.0),
67         m_setfocallength(false),
68         m_noOfScanlines(32),
69         m_motionblur(0),
70         m_motionblurvalue(-1.0),
71         m_texco_num(0),
72         m_attrib_num(0),
73         m_last_blendmode(GPU_BLEND_SOLID),
74         m_last_frontface(true),
75         m_materialCachingInfo(0)
76 {
77         m_viewmatrix.setIdentity();
78         m_viewinvmatrix.setIdentity();
79         
80         for (int i = 0; i < 32; i++)
81         {
82                 left_eye_vinterlace_mask[i] = 0x55555555;
83                 right_eye_vinterlace_mask[i] = 0xAAAAAAAA;
84                 hinterlace_mask[i] = (i&1)*0xFFFFFFFF;
85         }
86         hinterlace_mask[32] = 0;
87 }
88
89
90
91 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
92 {
93 }
94
95 bool RAS_OpenGLRasterizer::Init()
96 {
97         GPU_state_init();
98
99         m_redback = 0.4375;
100         m_greenback = 0.4375;
101         m_blueback = 0.4375;
102         m_alphaback = 0.0;
103         
104         m_ambr = 0.0f;
105         m_ambg = 0.0f;
106         m_ambb = 0.0f;
107
108         glDisable(GL_BLEND);
109         glDisable(GL_ALPHA_TEST);
110         m_last_blendmode = GPU_BLEND_SOLID;
111
112         glFrontFace(GL_CCW);
113         m_last_frontface = true;
114
115         glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
116         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
117         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
118
119         glShadeModel(GL_SMOOTH);
120
121         return true;
122 }
123
124
125 void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue)
126 {
127         m_ambr = red;
128         m_ambg = green;
129         m_ambb = blue;
130 }
131
132
133 void RAS_OpenGLRasterizer::SetAmbient(float factor)
134 {
135         float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f };
136         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
137 }
138
139
140 void RAS_OpenGLRasterizer::SetBackColor(float red,
141                                                                                 float green,
142                                                                                 float blue,
143                                                                                 float alpha)
144 {
145         m_redback = red;
146         m_greenback = green;
147         m_blueback = blue;
148         m_alphaback = alpha;
149 }
150
151
152
153 void RAS_OpenGLRasterizer::SetFogColor(float r,
154                                                                            float g,
155                                                                            float b)
156 {
157         m_fogr = r;
158         m_fogg = g;
159         m_fogb = b;
160         m_fogenabled = true;
161 }
162
163
164
165 void RAS_OpenGLRasterizer::SetFogStart(float start)
166 {
167         m_fogstart = start;
168         m_fogenabled = true;
169 }
170
171
172
173 void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
174 {
175         m_fogdist = fogend;
176         m_fogenabled = true;
177 }
178
179
180
181 void RAS_OpenGLRasterizer::SetFog(float start,
182                                                                   float dist,
183                                                                   float r,
184                                                                   float g,
185                                                                   float b)
186 {
187         m_fogstart = start;
188         m_fogdist = dist;
189         m_fogr = r;
190         m_fogg = g;
191         m_fogb = b;
192         m_fogenabled = true;
193 }
194
195
196
197 void RAS_OpenGLRasterizer::DisableFog()
198 {
199         m_fogenabled = false;
200 }
201
202
203
204 void RAS_OpenGLRasterizer::DisplayFog()
205 {
206         if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
207         {
208                 float params[5];
209                 glFogi(GL_FOG_MODE, GL_LINEAR);
210                 glFogf(GL_FOG_DENSITY, 0.1f);
211                 glFogf(GL_FOG_START, m_fogstart);
212                 glFogf(GL_FOG_END, m_fogstart + m_fogdist);
213                 params[0]= m_fogr;
214                 params[1]= m_fogg;
215                 params[2]= m_fogb;
216                 params[3]= 0.0;
217                 glFogfv(GL_FOG_COLOR, params); 
218                 glEnable(GL_FOG);
219         } 
220         else
221         {
222                 glDisable(GL_FOG);
223         }
224 }
225
226
227
228 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
229 {
230         return mat.Activate(this, m_materialCachingInfo);
231 }
232
233
234
235 void RAS_OpenGLRasterizer::Exit()
236 {
237
238         glEnable(GL_CULL_FACE);
239         glEnable(GL_DEPTH_TEST);
240         glClearDepth(1.0); 
241         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
242         glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
243         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
244         glDepthMask (GL_TRUE);
245         glDepthFunc(GL_LEQUAL);
246         glBlendFunc(GL_ONE, GL_ZERO);
247         
248         glDisable(GL_POLYGON_STIPPLE);
249         
250         glDisable(GL_LIGHTING);
251         if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
252                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
253         
254         EndFrame();
255 }
256
257 bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
258 {
259         m_time = time;
260         m_drawingmode = drawingmode;
261
262         // Blender camera routine destroys the settings
263         if (m_drawingmode < KX_SOLID)
264         {
265                 glDisable (GL_CULL_FACE);
266                 glDisable (GL_DEPTH_TEST);
267         }
268         else
269         {
270                 glEnable(GL_DEPTH_TEST);
271                 glEnable (GL_CULL_FACE);
272         }
273
274         glDisable(GL_BLEND);
275         glDisable(GL_ALPHA_TEST);
276         m_last_blendmode = GPU_BLEND_SOLID;
277
278         glFrontFace(GL_CCW);
279         m_last_frontface = true;
280
281         glShadeModel(GL_SMOOTH);
282
283         m_2DCanvas->BeginFrame();
284         
285         return true;
286 }
287
288
289
290 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
291 {
292         m_drawingmode = drawingmode;
293
294         if(m_drawingmode == KX_WIREFRAME)
295                 glDisable(GL_CULL_FACE);
296 }
297
298 int RAS_OpenGLRasterizer::GetDrawingMode()
299 {
300         return m_drawingmode;
301 }
302
303
304 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
305 {
306         glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
307 }
308
309
310 void RAS_OpenGLRasterizer::ClearColorBuffer()
311 {
312         m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
313         m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
314 }
315
316
317 void RAS_OpenGLRasterizer::ClearDepthBuffer()
318 {
319         m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
320 }
321
322
323 void RAS_OpenGLRasterizer::ClearCachingInfo(void)
324 {
325         m_materialCachingInfo = 0;
326 }
327
328
329 void RAS_OpenGLRasterizer::EndFrame()
330 {
331         glDisable(GL_LIGHTING);
332         glDisable(GL_TEXTURE_2D);
333
334         //DrawDebugLines
335         glBegin(GL_LINES);
336         for (unsigned int i=0;i<m_debugLines.size();i++)
337         {
338                 
339
340                 glColor4f(m_debugLines[i].m_color[0],m_debugLines[i].m_color[1],m_debugLines[i].m_color[2],1.f);
341                 const MT_Scalar* fromPtr = &m_debugLines[i].m_from.x();
342                 const MT_Scalar* toPtr= &m_debugLines[i].m_to.x();
343
344                 glVertex3dv(fromPtr);
345                 glVertex3dv(toPtr);
346         }
347         glEnd();
348
349         m_debugLines.clear();
350
351         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
352         m_2DCanvas->EndFrame();
353 }       
354
355 void RAS_OpenGLRasterizer::SetRenderArea()
356 {
357         // only above/below stereo method needs viewport adjustment
358         switch (m_stereomode)
359         {
360                 case RAS_STEREO_ABOVEBELOW:
361                         switch(m_curreye)
362                         {
363                                 case RAS_STEREO_LEFTEYE:
364                                         // upper half of window
365                                         m_2DCanvas->GetDisplayArea().SetLeft(0);
366                                         m_2DCanvas->GetDisplayArea().SetBottom(m_2DCanvas->GetHeight() -
367                                                 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
368         
369                                         m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
370                                         m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight()));
371                                         break;
372                                 case RAS_STEREO_RIGHTEYE:
373                                         // lower half of window
374                                         m_2DCanvas->GetDisplayArea().SetLeft(0);
375                                         m_2DCanvas->GetDisplayArea().SetBottom(0);
376                                         m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
377                                         m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
378                                         break;
379                         }
380                         break;
381                 case RAS_STEREO_SIDEBYSIDE:
382                         switch (m_curreye)
383                         {
384                                 case RAS_STEREO_LEFTEYE:
385                                         // Left half of window
386                                         m_2DCanvas->GetDisplayArea().SetLeft(0);
387                                         m_2DCanvas->GetDisplayArea().SetBottom(0);
388                                         m_2DCanvas->GetDisplayArea().SetRight(m_2DCanvas->GetWidth()/2);
389                                         m_2DCanvas->GetDisplayArea().SetTop(m_2DCanvas->GetHeight());
390                                         break;
391                                 case RAS_STEREO_RIGHTEYE:
392                                         // Right half of window
393                                         m_2DCanvas->GetDisplayArea().SetLeft(m_2DCanvas->GetWidth()/2);
394                                         m_2DCanvas->GetDisplayArea().SetBottom(0);
395                                         m_2DCanvas->GetDisplayArea().SetRight(m_2DCanvas->GetWidth());
396                                         m_2DCanvas->GetDisplayArea().SetTop(m_2DCanvas->GetHeight());
397                                         break;
398                         }
399                         break;
400                 default:
401                         // every available pixel
402                         m_2DCanvas->GetDisplayArea().SetLeft(0);
403                         m_2DCanvas->GetDisplayArea().SetBottom(0);
404                         m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
405                         m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight()));
406                         break;
407         }
408 }
409
410         
411 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
412 {
413         m_stereomode = stereomode;
414 }
415
416
417
418 bool RAS_OpenGLRasterizer::Stereo()
419 {
420         if(m_stereomode == RAS_STEREO_NOSTEREO)
421                 return false;
422         else
423                 return true;
424 }
425
426 bool RAS_OpenGLRasterizer::InterlacedStereo()
427 {
428         return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
429 }
430
431 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
432 {
433         m_curreye = eye;
434         switch (m_stereomode)
435         {
436                 case RAS_STEREO_QUADBUFFERED:
437                         glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
438                         break;
439                 case RAS_STEREO_ANAGLYPH:
440                         if (m_curreye == RAS_STEREO_LEFTEYE)
441                         {
442                                 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
443                         } else {
444                                 //glAccum(GL_LOAD, 1.0);
445                                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
446                                 ClearDepthBuffer();
447                         }
448                         break;
449                 case RAS_STEREO_VINTERLACE:
450                 {
451                         glEnable(GL_POLYGON_STIPPLE);
452                         glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
453                         if (m_curreye == RAS_STEREO_RIGHTEYE)
454                                 ClearDepthBuffer();
455                         break;
456                 }
457                 case RAS_STEREO_INTERLACED:
458                 {
459                         glEnable(GL_POLYGON_STIPPLE);
460                         glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
461                         if (m_curreye == RAS_STEREO_RIGHTEYE)
462                                 ClearDepthBuffer();
463                         break;
464                 }
465                 default:
466                         break;
467         }
468 }
469
470 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
471 {
472         return m_curreye;
473 }
474
475
476 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
477 {
478         m_eyeseparation = eyeseparation;
479         m_seteyesep = true;
480 }
481
482 float RAS_OpenGLRasterizer::GetEyeSeparation()
483 {
484         return m_eyeseparation;
485 }
486
487 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
488 {
489         m_focallength = focallength;
490         m_setfocallength = true;
491 }
492
493 float RAS_OpenGLRasterizer::GetFocalLength()
494 {
495         return m_focallength;
496 }
497
498
499 void RAS_OpenGLRasterizer::SwapBuffers()
500 {
501         m_2DCanvas->SwapBuffers();
502 }
503
504
505
506 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
507 {
508         return m_viewmatrix;
509 }
510
511 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
512 {
513         return m_viewinvmatrix;
514 }
515
516 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
517                                                                         class RAS_IPolyMaterial* polymat,
518                                                                         class RAS_IRenderTools* rendertools)
519
520         bool obcolor = ms.m_bObjectColor;
521         MT_Vector4& rgba = ms.m_RGBAcolor;
522         RAS_MeshSlot::iterator it;
523
524         // handle object color
525         if (obcolor) {
526                 glDisableClientState(GL_COLOR_ARRAY);
527                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
528         }
529         else
530                 glEnableClientState(GL_COLOR_ARRAY);
531
532         for(ms.begin(it); !ms.end(it); ms.next(it)) {
533                 RAS_TexVert *vertex;
534                 size_t i, j, numvert;
535                 
536                 numvert = it.array->m_type;
537
538                 if(it.array->m_type == RAS_DisplayArray::LINE) {
539                         // line drawing, no text
540                         glBegin(GL_LINES);
541
542                         for(i=0; i<it.totindex; i+=2)
543                         {
544                                 vertex = &it.vertex[it.index[i]];
545                                 glVertex3fv(vertex->getXYZ());
546
547                                 vertex = &it.vertex[it.index[i+1]];
548                                 glVertex3fv(vertex->getXYZ());
549                         }
550
551                         glEnd();
552                 }
553                 else {
554                         // triangle and quad text drawing
555                         for(i=0; i<it.totindex; i+=numvert)
556                         {
557                                 float v[4][3];
558                                 int glattrib, unit;
559
560                                 for(j=0; j<numvert; j++) {
561                                         vertex = &it.vertex[it.index[i+j]];
562
563                                         v[j][0] = vertex->getXYZ()[0];
564                                         v[j][1] = vertex->getXYZ()[1];
565                                         v[j][2] = vertex->getXYZ()[2];
566                                 }
567
568                                 // find the right opengl attribute
569                                 glattrib = -1;
570                                 if(GLEW_ARB_vertex_program)
571                                         for(unit=0; unit<m_attrib_num; unit++)
572                                                 if(m_attrib[unit] == RAS_TEXCO_UV1)
573                                                         glattrib = unit;
574                                 
575                                 rendertools->RenderText(polymat->GetDrawingMode(), polymat,
576                                         v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib);
577
578                                 ClearCachingInfo();
579                         }
580                 }
581         }
582
583         glDisableClientState(GL_COLOR_ARRAY);
584 }
585
586 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
587 {
588         m_texco_num = num;
589         if(m_texco_num > RAS_MAX_TEXCO)
590                 m_texco_num = RAS_MAX_TEXCO;
591 }
592
593 void RAS_OpenGLRasterizer::SetAttribNum(int num)
594 {
595         m_attrib_num = num;
596         if(m_attrib_num > RAS_MAX_ATTRIB)
597                 m_attrib_num = RAS_MAX_ATTRIB;
598 }
599
600 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
601 {
602         // this changes from material to material
603         if(unit < RAS_MAX_TEXCO)
604                 m_texco[unit] = coords;
605 }
606
607 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit)
608 {
609         // this changes from material to material
610         if(unit < RAS_MAX_ATTRIB)
611                 m_attrib[unit] = coords;
612 }
613
614 void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
615 {
616         int unit;
617
618         if(GLEW_ARB_multitexture) {
619                 for(unit=0; unit<m_texco_num; unit++) {
620                         if(tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
621                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
622                                 continue;
623                         }
624                         switch(m_texco[unit]) {
625                         case RAS_TEXCO_ORCO:
626                         case RAS_TEXCO_GLOB:
627                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
628                                 break;
629                         case RAS_TEXCO_UV1:
630                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
631                                 break;
632                         case RAS_TEXCO_NORM:
633                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal());
634                                 break;
635                         case RAS_TEXTANGENT:
636                                 glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent());
637                                 break;
638                         case RAS_TEXCO_UV2:
639                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
640                                 break;
641                         default:
642                                 break;
643                         }
644                 }
645         }
646
647         if(GLEW_ARB_vertex_program) {
648                 for(unit=0; unit<m_attrib_num; unit++) {
649                         switch(m_attrib[unit]) {
650                         case RAS_TEXCO_ORCO:
651                         case RAS_TEXCO_GLOB:
652                                 glVertexAttrib3fvARB(unit, tv.getXYZ());
653                                 break;
654                         case RAS_TEXCO_UV1:
655                                 glVertexAttrib2fvARB(unit, tv.getUV1());
656                                 break;
657                         case RAS_TEXCO_NORM:
658                                 glVertexAttrib3fvARB(unit, tv.getNormal());
659                                 break;
660                         case RAS_TEXTANGENT:
661                                 glVertexAttrib4fvARB(unit, tv.getTangent());
662                                 break;
663                         case RAS_TEXCO_UV2:
664                                 glVertexAttrib2fvARB(unit, tv.getUV2());
665                                 break;
666                         case RAS_TEXCO_VCOL:
667                                 glVertexAttrib4ubvARB(unit, tv.getRGBA());
668                                 break;
669                         default:
670                                 break;
671                         }
672                 }
673         }
674
675 }
676
677 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
678 {
679         IndexPrimitivesInternal(ms, false);
680 }
681
682 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
683 {
684         IndexPrimitivesInternal(ms, true);
685 }
686
687 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
688
689         bool obcolor = ms.m_bObjectColor;
690         bool wireframe = m_drawingmode <= KX_WIREFRAME;
691         MT_Vector4& rgba = ms.m_RGBAcolor;
692         RAS_MeshSlot::iterator it;
693
694         // iterate over display arrays, each containing an index + vertex array
695         for(ms.begin(it); !ms.end(it); ms.next(it)) {
696                 RAS_TexVert *vertex;
697                 size_t i, j, numvert;
698                 
699                 numvert = it.array->m_type;
700
701                 if(it.array->m_type == RAS_DisplayArray::LINE) {
702                         // line drawing
703                         glBegin(GL_LINES);
704
705                         for(i=0; i<it.totindex; i+=2)
706                         {
707                                 vertex = &it.vertex[it.index[i]];
708                                 glVertex3fv(vertex->getXYZ());
709
710                                 vertex = &it.vertex[it.index[i+1]];
711                                 glVertex3fv(vertex->getXYZ());
712                         }
713
714                         glEnd();
715                 }
716                 else {
717                         // triangle and quad drawing
718                         if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
719                                 glBegin(GL_TRIANGLES);
720                         else
721                                 glBegin(GL_QUADS);
722
723                         for(i=0; i<it.totindex; i+=numvert)
724                         {
725                                 if(obcolor)
726                                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
727
728                                 for(j=0; j<numvert; j++) {
729                                         vertex = &it.vertex[it.index[i+j]];
730
731                                         if(!wireframe) {
732                                                 if(!obcolor)
733                                                         glColor4ubv((const GLubyte *)(vertex->getRGBA()));
734
735                                                 glNormal3fv(vertex->getNormal());
736
737                                                 if(multi)
738                                                         TexCoord(*vertex);
739                                                 else
740                                                         glTexCoord2fv(vertex->getUV1());
741                                         }
742
743                                         glVertex3fv(vertex->getXYZ());
744                                 }
745                         }
746
747                         glEnd();
748                 }
749         }
750 }
751
752 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
753 {
754         glMatrixMode(GL_PROJECTION);
755         double* matrix = &mat(0,0);
756         glLoadMatrixd(matrix);
757 }
758
759
760 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
761 {
762         glMatrixMode(GL_PROJECTION);
763         double matrix[16];
764         /* Get into argument. Looks a bit dodgy, but it's ok. */
765         mat.getValue(matrix);
766         /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
767         glLoadMatrixd(matrix);  
768 }
769
770 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
771         float left,
772         float right,
773         float bottom,
774         float top,
775         float frustnear,
776         float frustfar,
777         float focallength,
778         bool
779 ){
780         MT_Matrix4x4 result;
781         double mat[16];
782
783         // correction for stereo
784         if(m_stereomode != RAS_STEREO_NOSTEREO)
785         {
786                         float near_div_focallength;
787                         // next 2 params should be specified on command line and in Blender publisher
788                         if (!m_setfocallength)
789                                 m_focallength = (focallength == 0.f) ? 1.5 * right  // derived from example
790                                         : focallength; 
791                         if (!m_seteyesep)
792                                 m_eyeseparation = m_focallength/30;  // reasonable value...
793
794                         near_div_focallength = frustnear / m_focallength;
795                         switch(m_curreye)
796                         {
797                                 case RAS_STEREO_LEFTEYE:
798                                                 left += 0.5 * m_eyeseparation * near_div_focallength;
799                                                 right += 0.5 * m_eyeseparation * near_div_focallength;
800                                                 break;
801                                 case RAS_STEREO_RIGHTEYE:
802                                                 left -= 0.5 * m_eyeseparation * near_div_focallength;
803                                                 right -= 0.5 * m_eyeseparation * near_div_focallength;
804                                                 break;
805                         }
806                         // leave bottom, top, bottom and top untouched
807         }
808         
809         glMatrixMode(GL_PROJECTION);
810         glLoadIdentity();
811         glFrustum(left, right, bottom, top, frustnear, frustfar);
812                 
813         glGetDoublev(GL_PROJECTION_MATRIX, mat);
814         result.setValue(mat);
815
816         return result;
817 }
818
819
820 // next arguments probably contain redundant info, for later...
821 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos,
822                 const MT_Point3 &, const MT_Quaternion &camOrientQuat)
823 {
824         m_viewmatrix = mat;
825
826         // correction for stereo
827         if(m_stereomode != RAS_STEREO_NOSTEREO)
828         {
829                 MT_Matrix3x3 camOrientMat3x3(camOrientQuat);
830                 MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
831                 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
832                 MT_Vector3 viewDir, viewupVec;
833                 MT_Vector3 eyeline;
834
835                 // actual viewDir
836                 viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
837                 // actual viewup vec
838                 viewupVec = camOrientMat3x3 * unitViewupVec;
839
840                 // vector between eyes
841                 eyeline = viewDir.cross(viewupVec);
842
843                 switch(m_curreye)
844                 {
845                         case RAS_STEREO_LEFTEYE:
846                                 {
847                                 // translate to left by half the eye distance
848                                 MT_Transform transform;
849                                 transform.setIdentity();
850                                 transform.translate(-(eyeline * m_eyeseparation / 2.0));
851                                 m_viewmatrix *= transform;
852                                 }
853                                 break;
854                         case RAS_STEREO_RIGHTEYE:
855                                 {
856                                 // translate to right by half the eye distance
857                                 MT_Transform transform;
858                                 transform.setIdentity();
859                                 transform.translate(eyeline * m_eyeseparation / 2.0);
860                                 m_viewmatrix *= transform;
861                                 }
862                                 break;
863                 }
864         }
865
866         m_viewinvmatrix = m_viewmatrix;
867         m_viewinvmatrix.invert();
868
869         // note: getValue gives back column major as needed by OpenGL
870         MT_Scalar glviewmat[16];
871         m_viewmatrix.getValue(glviewmat);
872
873         glMatrixMode(GL_MODELVIEW);
874         glLoadMatrixd(glviewmat);
875         m_campos = campos;
876 }
877
878
879 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
880 {
881         return m_campos;
882 }
883
884
885 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
886 {
887         if (enable)
888                 glEnable(GL_CULL_FACE);
889         else
890                 glDisable(GL_CULL_FACE);
891 }
892
893 void RAS_OpenGLRasterizer::SetLines(bool enable)
894 {
895         if (enable)
896                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
897         else
898                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
899 }
900
901 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
902                                                                                   float specY,
903                                                                                   float specZ,
904                                                                                   float specval)
905 {
906         GLfloat mat_specular[] = {specX, specY, specZ, specval};
907         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
908 }
909
910
911
912 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
913 {
914         GLfloat mat_shininess[] = {     shiny };
915         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
916 }
917
918
919
920 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
921 {
922         GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
923         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
924 }
925
926 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
927 {
928         GLfloat mat_emit [] = {eX,eY,eZ,e};
929         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
930 }
931
932
933 double RAS_OpenGLRasterizer::GetTime()
934 {
935         return m_time;
936 }
937
938 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
939 {
940         glPolygonOffset(mult, add);
941         GLint mode = GL_POLYGON_OFFSET_FILL;
942         if (m_drawingmode < KX_SHADED)
943                 mode = GL_POLYGON_OFFSET_LINE;
944         if (mult != 0.0f || add != 0.0f)
945                 glEnable(mode);
946         else
947                 glDisable(mode);
948 }
949
950 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
951 {
952         m_motionblur = 1;
953         m_motionblurvalue = motionblurvalue;
954 }
955
956 void RAS_OpenGLRasterizer::DisableMotionBlur()
957 {
958         m_motionblur = 0;
959         m_motionblurvalue = -1.0;
960 }
961
962 void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode)
963 {
964         if(blendmode == m_last_blendmode)
965                 return;
966
967         if(blendmode == GPU_BLEND_SOLID) {
968                 glDisable(GL_BLEND);
969                 glDisable(GL_ALPHA_TEST);
970                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
971         }
972         else if(blendmode == GPU_BLEND_ADD) {
973                 glBlendFunc(GL_ONE, GL_ONE);
974                 glEnable(GL_BLEND);
975                 glDisable(GL_ALPHA_TEST);
976         }
977         else if(blendmode == GPU_BLEND_ALPHA) {
978                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
979                 glEnable(GL_BLEND);
980                 glEnable(GL_ALPHA_TEST);
981                 glAlphaFunc(GL_GREATER, 0.0f);
982         }
983         else if(blendmode == GPU_BLEND_CLIP) {
984                 glDisable(GL_BLEND); 
985                 glEnable(GL_ALPHA_TEST);
986                 glAlphaFunc(GL_GREATER, 0.5f);
987         }
988
989         m_last_blendmode = blendmode;
990 }
991
992 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
993 {
994         if(m_last_frontface == ccw)
995                 return;
996
997         if(ccw)
998                 glFrontFace(GL_CCW);
999         else
1000                 glFrontFace(GL_CW);
1001         
1002         m_last_frontface = ccw;
1003 }
1004