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