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