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