2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r18677...
[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 //DrawDebugLines
333         glDisable(GL_LIGHTING);
334         glDisable(GL_TEXTURE_2D);
335
336         glBegin(GL_LINES);
337         for (unsigned int i=0;i<m_debugLines.size();i++)
338         {
339                 
340
341                 glColor4f(m_debugLines[i].m_color[0],m_debugLines[i].m_color[1],m_debugLines[i].m_color[2],1.f);
342                 const MT_Scalar* fromPtr = &m_debugLines[i].m_from.x();
343                 const MT_Scalar* toPtr= &m_debugLines[i].m_to.x();
344
345                 glVertex3dv(fromPtr);
346                 glVertex3dv(toPtr);
347         }
348         glEnd();
349
350         glEnable(GL_LIGHTING);
351         glEnable(GL_TEXTURE_2D);
352
353         m_debugLines.clear();
354
355 }
356
357 void RAS_OpenGLRasterizer::EndFrame()
358 {
359         
360
361         FlushDebugLines();
362
363         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
364         m_2DCanvas->EndFrame();
365 }       
366
367 void RAS_OpenGLRasterizer::SetRenderArea()
368 {
369         // only above/below stereo method needs viewport adjustment
370         switch (m_stereomode)
371         {
372                 case RAS_STEREO_ABOVEBELOW:
373                         switch(m_curreye)
374                         {
375                                 case RAS_STEREO_LEFTEYE:
376                                         // upper half of window
377                                         m_2DCanvas->GetDisplayArea().SetLeft(0);
378                                         m_2DCanvas->GetDisplayArea().SetBottom(m_2DCanvas->GetHeight() -
379                                                 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
380         
381                                         m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
382                                         m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight()));
383                                         break;
384                                 case RAS_STEREO_RIGHTEYE:
385                                         // lower half of window
386                                         m_2DCanvas->GetDisplayArea().SetLeft(0);
387                                         m_2DCanvas->GetDisplayArea().SetBottom(0);
388                                         m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
389                                         m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
390                                         break;
391                         }
392                         break;
393                 case RAS_STEREO_SIDEBYSIDE:
394                         switch (m_curreye)
395                         {
396                                 case RAS_STEREO_LEFTEYE:
397                                         // Left half of window
398                                         m_2DCanvas->GetDisplayArea().SetLeft(0);
399                                         m_2DCanvas->GetDisplayArea().SetBottom(0);
400                                         m_2DCanvas->GetDisplayArea().SetRight(m_2DCanvas->GetWidth()/2);
401                                         m_2DCanvas->GetDisplayArea().SetTop(m_2DCanvas->GetHeight());
402                                         break;
403                                 case RAS_STEREO_RIGHTEYE:
404                                         // Right half of window
405                                         m_2DCanvas->GetDisplayArea().SetLeft(m_2DCanvas->GetWidth()/2);
406                                         m_2DCanvas->GetDisplayArea().SetBottom(0);
407                                         m_2DCanvas->GetDisplayArea().SetRight(m_2DCanvas->GetWidth());
408                                         m_2DCanvas->GetDisplayArea().SetTop(m_2DCanvas->GetHeight());
409                                         break;
410                         }
411                         break;
412                 default:
413                         // every available pixel
414                         m_2DCanvas->GetDisplayArea().SetLeft(0);
415                         m_2DCanvas->GetDisplayArea().SetBottom(0);
416                         m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
417                         m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight()));
418                         break;
419         }
420 }
421         
422 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
423 {
424         m_stereomode = stereomode;
425 }
426
427 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
428 {
429         return m_stereomode;
430 }
431
432 bool RAS_OpenGLRasterizer::Stereo()
433 {
434         if(m_stereomode == RAS_STEREO_NOSTEREO)
435                 return false;
436         else
437                 return true;
438 }
439
440 bool RAS_OpenGLRasterizer::InterlacedStereo()
441 {
442         return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
443 }
444
445 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
446 {
447         m_curreye = eye;
448         switch (m_stereomode)
449         {
450                 case RAS_STEREO_QUADBUFFERED:
451                         glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
452                         break;
453                 case RAS_STEREO_ANAGLYPH:
454                         if (m_curreye == RAS_STEREO_LEFTEYE)
455                         {
456                                 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
457                         } else {
458                                 //glAccum(GL_LOAD, 1.0);
459                                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
460                                 ClearDepthBuffer();
461                         }
462                         break;
463                 case RAS_STEREO_VINTERLACE:
464                 {
465                         glEnable(GL_POLYGON_STIPPLE);
466                         glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
467                         if (m_curreye == RAS_STEREO_RIGHTEYE)
468                                 ClearDepthBuffer();
469                         break;
470                 }
471                 case RAS_STEREO_INTERLACED:
472                 {
473                         glEnable(GL_POLYGON_STIPPLE);
474                         glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
475                         if (m_curreye == RAS_STEREO_RIGHTEYE)
476                                 ClearDepthBuffer();
477                         break;
478                 }
479                 default:
480                         break;
481         }
482 }
483
484 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
485 {
486         return m_curreye;
487 }
488
489
490 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
491 {
492         m_eyeseparation = eyeseparation;
493         m_seteyesep = true;
494 }
495
496 float RAS_OpenGLRasterizer::GetEyeSeparation()
497 {
498         return m_eyeseparation;
499 }
500
501 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
502 {
503         m_focallength = focallength;
504         m_setfocallength = true;
505 }
506
507 float RAS_OpenGLRasterizer::GetFocalLength()
508 {
509         return m_focallength;
510 }
511
512
513 void RAS_OpenGLRasterizer::SwapBuffers()
514 {
515         m_2DCanvas->SwapBuffers();
516 }
517
518
519
520 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
521 {
522         return m_viewmatrix;
523 }
524
525 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
526 {
527         return m_viewinvmatrix;
528 }
529
530 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
531                                                                         class RAS_IPolyMaterial* polymat,
532                                                                         class RAS_IRenderTools* rendertools)
533
534         bool obcolor = ms.m_bObjectColor;
535         MT_Vector4& rgba = ms.m_RGBAcolor;
536         RAS_MeshSlot::iterator it;
537
538         // handle object color
539         if (obcolor) {
540                 glDisableClientState(GL_COLOR_ARRAY);
541                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
542         }
543         else
544                 glEnableClientState(GL_COLOR_ARRAY);
545
546         for(ms.begin(it); !ms.end(it); ms.next(it)) {
547                 RAS_TexVert *vertex;
548                 size_t i, j, numvert;
549                 
550                 numvert = it.array->m_type;
551
552                 if(it.array->m_type == RAS_DisplayArray::LINE) {
553                         // line drawing, no text
554                         glBegin(GL_LINES);
555
556                         for(i=0; i<it.totindex; i+=2)
557                         {
558                                 vertex = &it.vertex[it.index[i]];
559                                 glVertex3fv(vertex->getXYZ());
560
561                                 vertex = &it.vertex[it.index[i+1]];
562                                 glVertex3fv(vertex->getXYZ());
563                         }
564
565                         glEnd();
566                 }
567                 else {
568                         // triangle and quad text drawing
569                         for(i=0; i<it.totindex; i+=numvert)
570                         {
571                                 float v[4][3];
572                                 int glattrib, unit;
573
574                                 for(j=0; j<numvert; j++) {
575                                         vertex = &it.vertex[it.index[i+j]];
576
577                                         v[j][0] = vertex->getXYZ()[0];
578                                         v[j][1] = vertex->getXYZ()[1];
579                                         v[j][2] = vertex->getXYZ()[2];
580                                 }
581
582                                 // find the right opengl attribute
583                                 glattrib = -1;
584                                 if(GLEW_ARB_vertex_program)
585                                         for(unit=0; unit<m_attrib_num; unit++)
586                                                 if(m_attrib[unit] == RAS_TEXCO_UV1)
587                                                         glattrib = unit;
588                                 
589                                 rendertools->RenderText(polymat->GetDrawingMode(), polymat,
590                                         v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib);
591
592                                 ClearCachingInfo();
593                         }
594                 }
595         }
596
597         glDisableClientState(GL_COLOR_ARRAY);
598 }
599
600 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
601 {
602         m_texco_num = num;
603         if(m_texco_num > RAS_MAX_TEXCO)
604                 m_texco_num = RAS_MAX_TEXCO;
605 }
606
607 void RAS_OpenGLRasterizer::SetAttribNum(int num)
608 {
609         m_attrib_num = num;
610         if(m_attrib_num > RAS_MAX_ATTRIB)
611                 m_attrib_num = RAS_MAX_ATTRIB;
612 }
613
614 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
615 {
616         // this changes from material to material
617         if(unit < RAS_MAX_TEXCO)
618                 m_texco[unit] = coords;
619 }
620
621 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit)
622 {
623         // this changes from material to material
624         if(unit < RAS_MAX_ATTRIB)
625                 m_attrib[unit] = coords;
626 }
627
628 void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
629 {
630         int unit;
631
632         if(GLEW_ARB_multitexture) {
633                 for(unit=0; unit<m_texco_num; unit++) {
634                         if(tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
635                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
636                                 continue;
637                         }
638                         switch(m_texco[unit]) {
639                         case RAS_TEXCO_ORCO:
640                         case RAS_TEXCO_GLOB:
641                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
642                                 break;
643                         case RAS_TEXCO_UV1:
644                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
645                                 break;
646                         case RAS_TEXCO_NORM:
647                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal());
648                                 break;
649                         case RAS_TEXTANGENT:
650                                 glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent());
651                                 break;
652                         case RAS_TEXCO_UV2:
653                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
654                                 break;
655                         default:
656                                 break;
657                         }
658                 }
659         }
660
661         if(GLEW_ARB_vertex_program) {
662                 for(unit=0; unit<m_attrib_num; unit++) {
663                         switch(m_attrib[unit]) {
664                         case RAS_TEXCO_ORCO:
665                         case RAS_TEXCO_GLOB:
666                                 glVertexAttrib3fvARB(unit, tv.getXYZ());
667                                 break;
668                         case RAS_TEXCO_UV1:
669                                 glVertexAttrib2fvARB(unit, tv.getUV1());
670                                 break;
671                         case RAS_TEXCO_NORM:
672                                 glVertexAttrib3fvARB(unit, tv.getNormal());
673                                 break;
674                         case RAS_TEXTANGENT:
675                                 glVertexAttrib4fvARB(unit, tv.getTangent());
676                                 break;
677                         case RAS_TEXCO_UV2:
678                                 glVertexAttrib2fvARB(unit, tv.getUV2());
679                                 break;
680                         case RAS_TEXCO_VCOL:
681                                 glVertexAttrib4ubvARB(unit, tv.getRGBA());
682                                 break;
683                         default:
684                                 break;
685                         }
686                 }
687         }
688
689 }
690
691 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
692 {
693         IndexPrimitivesInternal(ms, false);
694 }
695
696 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
697 {
698         IndexPrimitivesInternal(ms, true);
699 }
700
701 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
702
703         bool obcolor = ms.m_bObjectColor;
704         bool wireframe = m_drawingmode <= KX_WIREFRAME;
705         MT_Vector4& rgba = ms.m_RGBAcolor;
706         RAS_MeshSlot::iterator it;
707
708         // iterate over display arrays, each containing an index + vertex array
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
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 drawing
732                         if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
733                                 glBegin(GL_TRIANGLES);
734                         else
735                                 glBegin(GL_QUADS);
736
737                         for(i=0; i<it.totindex; i+=numvert)
738                         {
739                                 if(obcolor)
740                                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
741
742                                 for(j=0; j<numvert; j++) {
743                                         vertex = &it.vertex[it.index[i+j]];
744
745                                         if(!wireframe) {
746                                                 if(!obcolor)
747                                                         glColor4ubv((const GLubyte *)(vertex->getRGBA()));
748
749                                                 glNormal3fv(vertex->getNormal());
750
751                                                 if(multi)
752                                                         TexCoord(*vertex);
753                                                 else
754                                                         glTexCoord2fv(vertex->getUV1());
755                                         }
756
757                                         glVertex3fv(vertex->getXYZ());
758                                 }
759                         }
760
761                         glEnd();
762                 }
763         }
764 }
765
766 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
767 {
768         glMatrixMode(GL_PROJECTION);
769         double* matrix = &mat(0,0);
770         glLoadMatrixd(matrix);
771
772         m_camortho= (mat(3, 3) != 0.0f);
773 }
774
775 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
776 {
777         glMatrixMode(GL_PROJECTION);
778         double matrix[16];
779         /* Get into argument. Looks a bit dodgy, but it's ok. */
780         mat.getValue(matrix);
781         /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
782         glLoadMatrixd(matrix);  
783
784         m_camortho= (mat[3][3] != 0.0f);
785 }
786
787 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
788         float left,
789         float right,
790         float bottom,
791         float top,
792         float frustnear,
793         float frustfar,
794         float focallength,
795         bool 
796 ){
797         MT_Matrix4x4 result;
798         double mat[16];
799
800         // correction for stereo
801         if(m_stereomode != RAS_STEREO_NOSTEREO)
802         {
803                         float near_div_focallength;
804                         // next 2 params should be specified on command line and in Blender publisher
805                         if (!m_setfocallength)
806                                 m_focallength = (focallength == 0.f) ? 1.5 * right  // derived from example
807                                         : focallength; 
808                         if (!m_seteyesep)
809                                 m_eyeseparation = m_focallength/30;  // reasonable value...
810
811                         near_div_focallength = frustnear / m_focallength;
812                         switch(m_curreye)
813                         {
814                                 case RAS_STEREO_LEFTEYE:
815                                                 left += 0.5 * m_eyeseparation * near_div_focallength;
816                                                 right += 0.5 * m_eyeseparation * near_div_focallength;
817                                                 break;
818                                 case RAS_STEREO_RIGHTEYE:
819                                                 left -= 0.5 * m_eyeseparation * near_div_focallength;
820                                                 right -= 0.5 * m_eyeseparation * near_div_focallength;
821                                                 break;
822                         }
823                         // leave bottom, top, bottom and top untouched
824         }
825         
826         glMatrixMode(GL_PROJECTION);
827         glLoadIdentity();
828         glFrustum(left, right, bottom, top, frustnear, frustfar);
829                 
830         glGetDoublev(GL_PROJECTION_MATRIX, mat);
831         result.setValue(mat);
832
833         return result;
834 }
835
836
837 // next arguments probably contain redundant info, for later...
838 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos,
839                 const MT_Point3 &, const MT_Quaternion &camOrientQuat)
840 {
841         m_viewmatrix = mat;
842
843         // correction for stereo
844         if(m_stereomode != RAS_STEREO_NOSTEREO)
845         {
846                 MT_Matrix3x3 camOrientMat3x3(camOrientQuat);
847                 MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
848                 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
849                 MT_Vector3 viewDir, viewupVec;
850                 MT_Vector3 eyeline;
851
852                 // actual viewDir
853                 viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
854                 // actual viewup vec
855                 viewupVec = camOrientMat3x3 * unitViewupVec;
856
857                 // vector between eyes
858                 eyeline = viewDir.cross(viewupVec);
859
860                 switch(m_curreye)
861                 {
862                         case RAS_STEREO_LEFTEYE:
863                                 {
864                                 // translate to left by half the eye distance
865                                 MT_Transform transform;
866                                 transform.setIdentity();
867                                 transform.translate(-(eyeline * m_eyeseparation / 2.0));
868                                 m_viewmatrix *= transform;
869                                 }
870                                 break;
871                         case RAS_STEREO_RIGHTEYE:
872                                 {
873                                 // translate to right by half the eye distance
874                                 MT_Transform transform;
875                                 transform.setIdentity();
876                                 transform.translate(eyeline * m_eyeseparation / 2.0);
877                                 m_viewmatrix *= transform;
878                                 }
879                                 break;
880                 }
881         }
882
883         m_viewinvmatrix = m_viewmatrix;
884         m_viewinvmatrix.invert();
885
886         // note: getValue gives back column major as needed by OpenGL
887         MT_Scalar glviewmat[16];
888         m_viewmatrix.getValue(glviewmat);
889
890         glMatrixMode(GL_MODELVIEW);
891         glLoadMatrixd(glviewmat);
892         m_campos = campos;
893 }
894
895
896 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
897 {
898         return m_campos;
899 }
900
901 bool RAS_OpenGLRasterizer::GetCameraOrtho()
902 {
903         return m_camortho;
904 }
905
906 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
907 {
908         if (enable)
909                 glEnable(GL_CULL_FACE);
910         else
911                 glDisable(GL_CULL_FACE);
912 }
913
914 void RAS_OpenGLRasterizer::SetLines(bool enable)
915 {
916         if (enable)
917                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
918         else
919                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
920 }
921
922 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
923                                                                                   float specY,
924                                                                                   float specZ,
925                                                                                   float specval)
926 {
927         GLfloat mat_specular[] = {specX, specY, specZ, specval};
928         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
929 }
930
931
932
933 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
934 {
935         GLfloat mat_shininess[] = {     shiny };
936         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
937 }
938
939
940
941 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
942 {
943         GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
944         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
945 }
946
947 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
948 {
949         GLfloat mat_emit [] = {eX,eY,eZ,e};
950         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
951 }
952
953
954 double RAS_OpenGLRasterizer::GetTime()
955 {
956         return m_time;
957 }
958
959 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
960 {
961         glPolygonOffset(mult, add);
962         GLint mode = GL_POLYGON_OFFSET_FILL;
963         if (m_drawingmode < KX_SHADED)
964                 mode = GL_POLYGON_OFFSET_LINE;
965         if (mult != 0.0f || add != 0.0f)
966                 glEnable(mode);
967         else
968                 glDisable(mode);
969 }
970
971 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
972 {
973         /* don't just set m_motionblur to 1, but check if it is 0 so
974          * we don't reset a motion blur that is already enabled */
975         if(m_motionblur == 0)
976                 m_motionblur = 1;
977         m_motionblurvalue = motionblurvalue;
978 }
979
980 void RAS_OpenGLRasterizer::DisableMotionBlur()
981 {
982         m_motionblur = 0;
983         m_motionblurvalue = -1.0;
984 }
985
986 void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode)
987 {
988         if(blendmode == m_last_blendmode)
989                 return;
990
991         if(blendmode == GPU_BLEND_SOLID) {
992                 glDisable(GL_BLEND);
993                 glDisable(GL_ALPHA_TEST);
994                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
995         }
996         else if(blendmode == GPU_BLEND_ADD) {
997                 glBlendFunc(GL_ONE, GL_ONE);
998                 glEnable(GL_BLEND);
999                 glDisable(GL_ALPHA_TEST);
1000         }
1001         else if(blendmode == GPU_BLEND_ALPHA) {
1002                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1003                 glEnable(GL_BLEND);
1004                 glEnable(GL_ALPHA_TEST);
1005                 glAlphaFunc(GL_GREATER, 0.0f);
1006         }
1007         else if(blendmode == GPU_BLEND_CLIP) {
1008                 glDisable(GL_BLEND); 
1009                 glEnable(GL_ALPHA_TEST);
1010                 glAlphaFunc(GL_GREATER, 0.5f);
1011         }
1012
1013         m_last_blendmode = blendmode;
1014 }
1015
1016 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
1017 {
1018         if(m_last_frontface == ccw)
1019                 return;
1020
1021         if(ccw)
1022                 glFrontFace(GL_CCW);
1023         else
1024                 glFrontFace(GL_CW);
1025         
1026         m_last_frontface = ccw;
1027 }
1028