svn merge ^/trunk/blender -r45364:HEAD --accept postpone
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_OpenGLRasterizer.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
29  *  \ingroup bgerastogl
30  */
31
32  
33 #include <math.h>
34 #include <stdlib.h>
35  
36 #include "RAS_OpenGLRasterizer.h"
37
38 #include "GL/glew.h"
39
40 #include "RAS_Rect.h"
41 #include "RAS_TexVert.h"
42 #include "RAS_MeshObject.h"
43 #include "MT_CmMatrix4x4.h"
44 #include "RAS_IRenderTools.h" // rendering text
45
46 #include "GPU_draw.h"
47 #include "GPU_material.h"
48 #include "GPU_extensions.h"
49
50 #include "DNA_image_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_material_types.h"
53 #include "DNA_scene_types.h"
54
55 #include "BKE_DerivedMesh.h"
56
57 #ifndef M_PI
58 #define M_PI            3.14159265358979323846
59 #endif
60
61 /**
62  *  32x32 bit masks for vinterlace stereo mode
63  */
64 static GLuint left_eye_vinterlace_mask[32];
65 static GLuint right_eye_vinterlace_mask[32];
66
67 /**
68  *  32x32 bit masks for hinterlace stereo mode.
69  *  Left eye = &hinterlace_mask[0]
70  *  Right eye = &hinterlace_mask[1]
71  */
72 static GLuint hinterlace_mask[33];
73
74 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
75         :RAS_IRasterizer(canvas),
76         m_2DCanvas(canvas),
77         m_fogenabled(false),
78         m_time(0.0),
79         m_campos(0.0f, 0.0f, 0.0f),
80         m_camortho(false),
81         m_stereomode(RAS_STEREO_NOSTEREO),
82         m_curreye(RAS_STEREO_LEFTEYE),
83         m_eyeseparation(0.0),
84         m_focallength(0.0),
85         m_setfocallength(false),
86         m_noOfScanlines(32),
87         m_motionblur(0),
88         m_motionblurvalue(-1.0),
89         m_texco_num(0),
90         m_attrib_num(0),
91         //m_last_alphablend(GPU_BLEND_SOLID),
92         m_last_frontface(true),
93         m_materialCachingInfo(0)
94 {
95         m_viewmatrix.setIdentity();
96         m_viewinvmatrix.setIdentity();
97         
98         for (int i = 0; i < 32; i++)
99         {
100                 left_eye_vinterlace_mask[i] = 0x55555555;
101                 right_eye_vinterlace_mask[i] = 0xAAAAAAAA;
102                 hinterlace_mask[i] = (i&1)*0xFFFFFFFF;
103         }
104         hinterlace_mask[32] = 0;
105
106         m_prevafvalue = GPU_get_anisotropic();
107 }
108
109
110
111 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
112 {
113         // Restore the previous AF value
114         GPU_set_anisotropic(m_prevafvalue);
115 }
116
117 bool RAS_OpenGLRasterizer::Init()
118 {
119         GPU_state_init();
120
121
122         m_ambr = 0.0f;
123         m_ambg = 0.0f;
124         m_ambb = 0.0f;
125
126         glDisable(GL_BLEND);
127         glDisable(GL_ALPHA_TEST);
128         //m_last_alphablend = GPU_BLEND_SOLID;
129         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
130
131         glFrontFace(GL_CCW);
132         m_last_frontface = true;
133
134         m_redback = 0.4375;
135         m_greenback = 0.4375;
136         m_blueback = 0.4375;
137         m_alphaback = 0.0;
138
139         glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
140         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
141         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
142
143
144         glShadeModel(GL_SMOOTH);
145
146         return true;
147 }
148
149
150 void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue)
151 {
152         m_ambr = red;
153         m_ambg = green;
154         m_ambb = blue;
155 }
156
157
158 void RAS_OpenGLRasterizer::SetAmbient(float factor)
159 {
160         float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f };
161         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
162 }
163
164
165 void RAS_OpenGLRasterizer::SetBackColor(float red,
166                                                                                 float green,
167                                                                                 float blue,
168                                                                                 float alpha)
169 {
170         m_redback = red;
171         m_greenback = green;
172         m_blueback = blue;
173         m_alphaback = alpha;
174 }
175
176
177
178 void RAS_OpenGLRasterizer::SetFogColor(float r,
179                                                                            float g,
180                                                                            float b)
181 {
182         m_fogr = r;
183         m_fogg = g;
184         m_fogb = b;
185         m_fogenabled = true;
186 }
187
188
189
190 void RAS_OpenGLRasterizer::SetFogStart(float start)
191 {
192         m_fogstart = start;
193         m_fogenabled = true;
194 }
195
196
197
198 void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
199 {
200         m_fogdist = fogend;
201         m_fogenabled = true;
202 }
203
204
205
206 void RAS_OpenGLRasterizer::SetFog(float start,
207                                                                   float dist,
208                                                                   float r,
209                                                                   float g,
210                                                                   float b)
211 {
212         m_fogstart = start;
213         m_fogdist = dist;
214         m_fogr = r;
215         m_fogg = g;
216         m_fogb = b;
217         m_fogenabled = true;
218 }
219
220
221
222 void RAS_OpenGLRasterizer::DisableFog()
223 {
224         m_fogenabled = false;
225 }
226
227 bool RAS_OpenGLRasterizer::IsFogEnabled()
228 {
229         return m_fogenabled;
230 }
231
232
233 void RAS_OpenGLRasterizer::DisplayFog()
234 {
235         if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
236         {
237                 float params[5];
238                 glFogi(GL_FOG_MODE, GL_LINEAR);
239                 glFogf(GL_FOG_DENSITY, 0.1f);
240                 glFogf(GL_FOG_START, m_fogstart);
241                 glFogf(GL_FOG_END, m_fogstart + m_fogdist);
242                 params[0]= m_fogr;
243                 params[1]= m_fogg;
244                 params[2]= m_fogb;
245                 params[3]= 0.0;
246                 glFogfv(GL_FOG_COLOR, params); 
247                 glEnable(GL_FOG);
248         } 
249         else
250         {
251                 glDisable(GL_FOG);
252         }
253 }
254
255
256
257 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
258 {
259         return mat.Activate(this, m_materialCachingInfo);
260 }
261
262
263
264 void RAS_OpenGLRasterizer::Exit()
265 {
266
267         glEnable(GL_CULL_FACE);
268         glEnable(GL_DEPTH_TEST);
269         glClearDepth(1.0); 
270         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
271         glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
272         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
273         glDepthMask (GL_TRUE);
274         glDepthFunc(GL_LEQUAL);
275         glBlendFunc(GL_ONE, GL_ZERO);
276         
277         glDisable(GL_POLYGON_STIPPLE);
278         
279         glDisable(GL_LIGHTING);
280         if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
281                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
282         
283         EndFrame();
284 }
285
286 bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
287 {
288         m_time = time;
289         m_drawingmode = drawingmode;
290
291         // Blender camera routine destroys the settings
292         if (m_drawingmode < KX_SOLID)
293         {
294                 glDisable (GL_CULL_FACE);
295                 glDisable (GL_DEPTH_TEST);
296         }
297         else
298         {
299                 glEnable(GL_DEPTH_TEST);
300                 glEnable (GL_CULL_FACE);
301         }
302
303         glDisable(GL_BLEND);
304         glDisable(GL_ALPHA_TEST);
305         //m_last_alphablend = GPU_BLEND_SOLID;
306         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
307
308         glFrontFace(GL_CCW);
309         m_last_frontface = true;
310
311         glShadeModel(GL_SMOOTH);
312
313         glEnable(GL_MULTISAMPLE_ARB);
314
315         m_2DCanvas->BeginFrame();
316         
317         return true;
318 }
319
320
321
322 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
323 {
324         m_drawingmode = drawingmode;
325
326         if (m_drawingmode == KX_WIREFRAME)
327                 glDisable(GL_CULL_FACE);
328 }
329
330 int RAS_OpenGLRasterizer::GetDrawingMode()
331 {
332         return m_drawingmode;
333 }
334
335
336 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
337 {
338         glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
339 }
340
341
342 void RAS_OpenGLRasterizer::ClearColorBuffer()
343 {
344         m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
345         m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
346 }
347
348
349 void RAS_OpenGLRasterizer::ClearDepthBuffer()
350 {
351         m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
352 }
353
354
355 void RAS_OpenGLRasterizer::ClearCachingInfo(void)
356 {
357         m_materialCachingInfo = 0;
358 }
359
360 void RAS_OpenGLRasterizer::FlushDebugShapes()
361 {
362         if (!m_debugShapes.size())
363                 return;
364
365         // DrawDebugLines
366         GLboolean light, tex;
367
368         light= glIsEnabled(GL_LIGHTING);
369         tex= glIsEnabled(GL_TEXTURE_2D);
370
371         if (light) glDisable(GL_LIGHTING);
372         if (tex) glDisable(GL_TEXTURE_2D);
373
374         //draw lines
375         glBegin(GL_LINES);
376         for (unsigned int i=0;i<m_debugShapes.size();i++)
377         {
378                 if (m_debugShapes[i].m_type != OglDebugShape::LINE)
379                         continue;
380                 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
381                 const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x();
382                 const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x();
383                 glVertex3dv(fromPtr);
384                 glVertex3dv(toPtr);
385         }
386         glEnd();
387
388         //draw circles
389         for (unsigned int i=0;i<m_debugShapes.size();i++)
390         {
391                 if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE)
392                         continue;
393                 glBegin(GL_LINE_LOOP);
394                 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
395
396                 static const MT_Vector3 worldUp(0.0, 0.0, 1.0);
397                 MT_Vector3 norm = m_debugShapes[i].m_param;
398                 MT_Matrix3x3 tr;
399                 if (norm.fuzzyZero() || norm == worldUp)
400                 {
401                         tr.setIdentity();
402                 }
403                 else
404                 {
405                         MT_Vector3 xaxis, yaxis;
406                         xaxis = MT_cross(norm, worldUp);
407                         yaxis = MT_cross(xaxis, norm);
408                         tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(),
409                                 yaxis.x(), yaxis.y(), yaxis.z(),
410                                 norm.x(), norm.y(), norm.z());
411                 }
412                 MT_Scalar rad = m_debugShapes[i].m_param2.x();
413                 int n = (int) m_debugShapes[i].m_param2.y();
414                 for (int j = 0; j<n; j++)
415                 {
416                         MT_Scalar theta = j*M_PI*2/n;
417                         MT_Vector3 pos(cos(theta) * rad, sin(theta) * rad, 0.0);
418                         pos = pos*tr;
419                         pos += m_debugShapes[i].m_pos;
420                         const MT_Scalar* posPtr = &pos.x();
421                         glVertex3dv(posPtr);
422                 }
423                 glEnd();
424         }
425
426         if (light) glEnable(GL_LIGHTING);
427         if (tex) glEnable(GL_TEXTURE_2D);
428
429         m_debugShapes.clear();
430 }
431
432 void RAS_OpenGLRasterizer::EndFrame()
433 {
434         FlushDebugShapes();
435
436         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
437
438         glDisable(GL_MULTISAMPLE_ARB);
439
440         m_2DCanvas->EndFrame();
441 }       
442
443 void RAS_OpenGLRasterizer::SetRenderArea()
444 {
445         RAS_Rect area;
446         // only above/below stereo method needs viewport adjustment
447         switch (m_stereomode)
448         {
449                 case RAS_STEREO_ABOVEBELOW:
450                         switch(m_curreye)
451                         {
452                                 case RAS_STEREO_LEFTEYE:
453                                         // upper half of window
454                                         area.SetLeft(0);
455                                         area.SetBottom(m_2DCanvas->GetHeight() -
456                                                 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
457         
458                                         area.SetRight(int(m_2DCanvas->GetWidth()));
459                                         area.SetTop(int(m_2DCanvas->GetHeight()));
460                                         m_2DCanvas->SetDisplayArea(&area);
461                                         break;
462                                 case RAS_STEREO_RIGHTEYE:
463                                         // lower half of window
464                                         area.SetLeft(0);
465                                         area.SetBottom(0);
466                                         area.SetRight(int(m_2DCanvas->GetWidth()));
467                                         area.SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
468                                         m_2DCanvas->SetDisplayArea(&area);
469                                         break;
470                         }
471                         break;
472                 case RAS_STEREO_SIDEBYSIDE:
473                         switch (m_curreye)
474                         {
475                                 case RAS_STEREO_LEFTEYE:
476                                         // Left half of window
477                                         area.SetLeft(0);
478                                         area.SetBottom(0);
479                                         area.SetRight(m_2DCanvas->GetWidth()/2);
480                                         area.SetTop(m_2DCanvas->GetHeight());
481                                         m_2DCanvas->SetDisplayArea(&area);
482                                         break;
483                                 case RAS_STEREO_RIGHTEYE:
484                                         // Right half of window
485                                         area.SetLeft(m_2DCanvas->GetWidth()/2);
486                                         area.SetBottom(0);
487                                         area.SetRight(m_2DCanvas->GetWidth());
488                                         area.SetTop(m_2DCanvas->GetHeight());
489                                         m_2DCanvas->SetDisplayArea(&area);
490                                         break;
491                         }
492                         break;
493                 default:
494                         // every available pixel
495                         area.SetLeft(0);
496                         area.SetBottom(0);
497                         area.SetRight(int(m_2DCanvas->GetWidth()));
498                         area.SetTop(int(m_2DCanvas->GetHeight()));
499                         m_2DCanvas->SetDisplayArea(&area);
500                         break;
501         }
502 }
503         
504 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
505 {
506         m_stereomode = stereomode;
507 }
508
509 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
510 {
511         return m_stereomode;
512 }
513
514 bool RAS_OpenGLRasterizer::Stereo()
515 {
516         if (m_stereomode > RAS_STEREO_NOSTEREO) // > 0
517                 return true;
518         else
519                 return false;
520 }
521
522 bool RAS_OpenGLRasterizer::InterlacedStereo()
523 {
524         return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
525 }
526
527 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
528 {
529         m_curreye = eye;
530         switch (m_stereomode)
531         {
532                 case RAS_STEREO_QUADBUFFERED:
533                         glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
534                         break;
535                 case RAS_STEREO_ANAGLYPH:
536                         if (m_curreye == RAS_STEREO_LEFTEYE)
537                         {
538                                 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
539                         } else {
540                                 //glAccum(GL_LOAD, 1.0);
541                                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
542                                 ClearDepthBuffer();
543                         }
544                         break;
545                 case RAS_STEREO_VINTERLACE:
546                 {
547                         glEnable(GL_POLYGON_STIPPLE);
548                         glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
549                         if (m_curreye == RAS_STEREO_RIGHTEYE)
550                                 ClearDepthBuffer();
551                         break;
552                 }
553                 case RAS_STEREO_INTERLACED:
554                 {
555                         glEnable(GL_POLYGON_STIPPLE);
556                         glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
557                         if (m_curreye == RAS_STEREO_RIGHTEYE)
558                                 ClearDepthBuffer();
559                         break;
560                 }
561                 default:
562                         break;
563         }
564 }
565
566 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
567 {
568         return m_curreye;
569 }
570
571
572 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
573 {
574         m_eyeseparation = eyeseparation;
575 }
576
577 float RAS_OpenGLRasterizer::GetEyeSeparation()
578 {
579         return m_eyeseparation;
580 }
581
582 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
583 {
584         m_focallength = focallength;
585         m_setfocallength = true;
586 }
587
588 float RAS_OpenGLRasterizer::GetFocalLength()
589 {
590         return m_focallength;
591 }
592
593
594 void RAS_OpenGLRasterizer::SwapBuffers()
595 {
596         m_2DCanvas->SwapBuffers();
597 }
598
599
600
601 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
602 {
603         return m_viewmatrix;
604 }
605
606 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
607 {
608         return m_viewinvmatrix;
609 }
610
611 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
612                                                                         class RAS_IPolyMaterial* polymat,
613                                                                         class RAS_IRenderTools* rendertools)
614
615         bool obcolor = ms.m_bObjectColor;
616         MT_Vector4& rgba = ms.m_RGBAcolor;
617         RAS_MeshSlot::iterator it;
618
619         // handle object color
620         if (obcolor) {
621                 glDisableClientState(GL_COLOR_ARRAY);
622                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
623         }
624         else
625                 glEnableClientState(GL_COLOR_ARRAY);
626
627         for (ms.begin(it); !ms.end(it); ms.next(it)) {
628                 RAS_TexVert *vertex;
629                 size_t i, j, numvert;
630                 
631                 numvert = it.array->m_type;
632
633                 if (it.array->m_type == RAS_DisplayArray::LINE) {
634                         // line drawing, no text
635                         glBegin(GL_LINES);
636
637                         for (i=0; i<it.totindex; i+=2)
638                         {
639                                 vertex = &it.vertex[it.index[i]];
640                                 glVertex3fv(vertex->getXYZ());
641
642                                 vertex = &it.vertex[it.index[i+1]];
643                                 glVertex3fv(vertex->getXYZ());
644                         }
645
646                         glEnd();
647                 }
648                 else {
649                         // triangle and quad text drawing
650                         for (i=0; i<it.totindex; i+=numvert)
651                         {
652                                 float v[4][3];
653                                 int glattrib, unit;
654
655                                 for (j=0; j<numvert; j++) {
656                                         vertex = &it.vertex[it.index[i+j]];
657
658                                         v[j][0] = vertex->getXYZ()[0];
659                                         v[j][1] = vertex->getXYZ()[1];
660                                         v[j][2] = vertex->getXYZ()[2];
661                                 }
662
663                                 // find the right opengl attribute
664                                 glattrib = -1;
665                                 if (GLEW_ARB_vertex_program)
666                                         for (unit=0; unit<m_attrib_num; unit++)
667                                                 if (m_attrib[unit] == RAS_TEXCO_UV1)
668                                                         glattrib = unit;
669                                 
670                                 rendertools->RenderText(polymat->GetDrawingMode(), polymat,
671                                         v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib);
672
673                                 ClearCachingInfo();
674                         }
675                 }
676         }
677
678         glDisableClientState(GL_COLOR_ARRAY);
679 }
680
681 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
682 {
683         m_texco_num = num;
684         if (m_texco_num > RAS_MAX_TEXCO)
685                 m_texco_num = RAS_MAX_TEXCO;
686 }
687
688 void RAS_OpenGLRasterizer::SetAttribNum(int num)
689 {
690         m_attrib_num = num;
691         if (m_attrib_num > RAS_MAX_ATTRIB)
692                 m_attrib_num = RAS_MAX_ATTRIB;
693 }
694
695 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
696 {
697         // this changes from material to material
698         if (unit < RAS_MAX_TEXCO)
699                 m_texco[unit] = coords;
700 }
701
702 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit)
703 {
704         // this changes from material to material
705         if (unit < RAS_MAX_ATTRIB)
706                 m_attrib[unit] = coords;
707 }
708
709 void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
710 {
711         int unit;
712
713         if (GLEW_ARB_multitexture) {
714                 for (unit=0; unit<m_texco_num; unit++) {
715                         if (tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
716                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
717                                 continue;
718                         }
719                         switch(m_texco[unit]) {
720                         case RAS_TEXCO_ORCO:
721                         case RAS_TEXCO_GLOB:
722                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
723                                 break;
724                         case RAS_TEXCO_UV1:
725                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
726                                 break;
727                         case RAS_TEXCO_NORM:
728                                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal());
729                                 break;
730                         case RAS_TEXTANGENT:
731                                 glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent());
732                                 break;
733                         case RAS_TEXCO_UV2:
734                                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
735                                 break;
736                         default:
737                                 break;
738                         }
739                 }
740         }
741
742         if (GLEW_ARB_vertex_program) {
743                 for (unit=0; unit<m_attrib_num; unit++) {
744                         switch(m_attrib[unit]) {
745                         case RAS_TEXCO_ORCO:
746                         case RAS_TEXCO_GLOB:
747                                 glVertexAttrib3fvARB(unit, tv.getXYZ());
748                                 break;
749                         case RAS_TEXCO_UV1:
750                                 glVertexAttrib2fvARB(unit, tv.getUV1());
751                                 break;
752                         case RAS_TEXCO_NORM:
753                                 glVertexAttrib3fvARB(unit, tv.getNormal());
754                                 break;
755                         case RAS_TEXTANGENT:
756                                 glVertexAttrib4fvARB(unit, tv.getTangent());
757                                 break;
758                         case RAS_TEXCO_UV2:
759                                 glVertexAttrib2fvARB(unit, tv.getUV2());
760                                 break;
761                         case RAS_TEXCO_VCOL:
762                                 glVertexAttrib4ubvARB(unit, tv.getRGBA());
763                                 break;
764                         default:
765                                 break;
766                         }
767                 }
768         }
769
770 }
771
772 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
773 {
774         IndexPrimitivesInternal(ms, false);
775 }
776
777 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
778 {
779         IndexPrimitivesInternal(ms, true);
780 }
781
782 static bool current_wireframe;
783 static RAS_MaterialBucket *current_bucket;
784 static RAS_IPolyMaterial *current_polymat;
785 static RAS_MeshSlot *current_ms;
786 static RAS_MeshObject *current_mesh;
787 static int current_blmat_nr;
788 static GPUVertexAttribs current_gpu_attribs;
789 static Image *current_image;
790 static int CheckMaterialDM(int matnr, void *attribs)
791 {
792         // only draw the current material
793         if (matnr != current_blmat_nr)
794                 return 0;
795         GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
796         if (gattribs)
797                 memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
798         return 1;
799 }
800
801 /*
802 static int CheckTexfaceDM(void *mcol, int index)
803 {
804
805         // index is the original face index, retrieve the polygon
806         RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
807                 current_mesh->GetPolygon(index) : NULL;
808         if (polygon && polygon->GetMaterial() == current_bucket) {
809                 // must handle color.
810                 if (current_wireframe)
811                         return 2;
812                 if (current_ms->m_bObjectColor) {
813                         MT_Vector4& rgba = current_ms->m_RGBAcolor;
814                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
815                         // don't use mcol
816                         return 2;
817                 }
818                 if (!mcol) {
819                         // we have to set the color from the material
820                         unsigned char rgba[4];
821                         current_polymat->GetMaterialRGBAColor(rgba);
822                         glColor4ubv((const GLubyte *)rgba);
823                         return 2;
824                 }
825                 return 1;
826         }
827         return 0;
828 }
829 */
830
831 static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr)
832 {
833
834         // index is the original face index, retrieve the polygon
835         if (matnr == current_blmat_nr &&
836                 (tface == NULL || tface->tpage == current_image)) {
837                 // must handle color.
838                 if (current_wireframe)
839                         return DM_DRAW_OPTION_NO_MCOL;
840                 if (current_ms->m_bObjectColor) {
841                         MT_Vector4& rgba = current_ms->m_RGBAcolor;
842                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
843                         // don't use mcol
844                         return DM_DRAW_OPTION_NO_MCOL;
845                 }
846                 if (!has_mcol) {
847                         // we have to set the color from the material
848                         unsigned char rgba[4];
849                         current_polymat->GetMaterialRGBAColor(rgba);
850                         glColor4ubv((const GLubyte *)rgba);
851                         return DM_DRAW_OPTION_NO_MCOL;
852                 }
853                 return DM_DRAW_OPTION_NORMAL;
854         }
855         return DM_DRAW_OPTION_SKIP;
856 }
857
858 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
859
860         bool obcolor = ms.m_bObjectColor;
861         bool wireframe = m_drawingmode <= KX_WIREFRAME;
862         MT_Vector4& rgba = ms.m_RGBAcolor;
863         RAS_MeshSlot::iterator it;
864
865         if (ms.m_pDerivedMesh) {
866                 // mesh data is in derived mesh, 
867                 current_bucket = ms.m_bucket;
868                 current_polymat = current_bucket->GetPolyMaterial();
869                 current_ms = &ms;
870                 current_mesh = ms.m_mesh;
871                 current_wireframe = wireframe;
872                 // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
873
874                 // handle two-side
875                 if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
876                         this->SetCullFace(true);
877                 else
878                         this->SetCullFace(false);
879
880                 if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
881                         // GetMaterialIndex return the original mface material index, 
882                         // increment by 1 to match what derived mesh is doing
883                         current_blmat_nr = current_polymat->GetMaterialIndex()+1;
884                         // For GLSL we need to retrieve the GPU material attribute
885                         Material* blmat = current_polymat->GetBlenderMaterial();
886                         Scene* blscene = current_polymat->GetBlenderScene();
887                         if (!wireframe && blscene && blmat)
888                                 GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), &current_gpu_attribs);
889                         else
890                                 memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
891                         // DM draw can mess up blending mode, restore at the end
892                         int current_blend_mode = GPU_get_material_alpha_blend();
893                         ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
894                         GPU_set_material_alpha_blend(current_blend_mode);
895                 } else {
896                         //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
897                         current_blmat_nr = current_polymat->GetMaterialIndex();
898                         current_image = current_polymat->GetBlenderImage();
899                         ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL);
900                 }
901                 return;
902         }
903         // iterate over display arrays, each containing an index + vertex array
904         for (ms.begin(it); !ms.end(it); ms.next(it)) {
905                 RAS_TexVert *vertex;
906                 size_t i, j, numvert;
907                 
908                 numvert = it.array->m_type;
909
910                 if (it.array->m_type == RAS_DisplayArray::LINE) {
911                         // line drawing
912                         glBegin(GL_LINES);
913
914                         for (i=0; i<it.totindex; i+=2)
915                         {
916                                 vertex = &it.vertex[it.index[i]];
917                                 glVertex3fv(vertex->getXYZ());
918
919                                 vertex = &it.vertex[it.index[i+1]];
920                                 glVertex3fv(vertex->getXYZ());
921                         }
922
923                         glEnd();
924                 }
925                 else {
926                         // triangle and quad drawing
927                         if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
928                                 glBegin(GL_TRIANGLES);
929                         else
930                                 glBegin(GL_QUADS);
931
932                         for (i=0; i<it.totindex; i+=numvert)
933                         {
934                                 if (obcolor)
935                                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
936
937                                 for (j=0; j<numvert; j++) {
938                                         vertex = &it.vertex[it.index[i+j]];
939
940                                         if (!wireframe) {
941                                                 if (!obcolor)
942                                                         glColor4ubv((const GLubyte *)(vertex->getRGBA()));
943
944                                                 glNormal3fv(vertex->getNormal());
945
946                                                 if (multi)
947                                                         TexCoord(*vertex);
948                                                 else
949                                                         glTexCoord2fv(vertex->getUV1());
950                                         }
951
952                                         glVertex3fv(vertex->getXYZ());
953                                 }
954                         }
955
956                         glEnd();
957                 }
958         }
959 }
960
961 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
962 {
963         glMatrixMode(GL_PROJECTION);
964         double* matrix = &mat(0,0);
965         glLoadMatrixd(matrix);
966
967         m_camortho= (mat(3, 3) != 0.0f);
968 }
969
970 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
971 {
972         glMatrixMode(GL_PROJECTION);
973         double matrix[16];
974         /* Get into argument. Looks a bit dodgy, but it's ok. */
975         mat.getValue(matrix);
976         /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
977         glLoadMatrixd(matrix);  
978
979         m_camortho= (mat[3][3] != 0.0f);
980 }
981
982 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
983         float left,
984         float right,
985         float bottom,
986         float top,
987         float frustnear,
988         float frustfar,
989         float focallength,
990         bool 
991 ) {
992         MT_Matrix4x4 result;
993         double mat[16];
994
995         // correction for stereo
996         if (Stereo())
997         {
998                         float near_div_focallength;
999                         float offset;
1000
1001                         // if Rasterizer.setFocalLength is not called we use the camera focallength
1002                         if (!m_setfocallength)
1003                                 // if focallength is null we use a value known to be reasonable
1004                                 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0
1005                                         : focallength;
1006
1007                         near_div_focallength = frustnear / m_focallength;
1008                         offset = 0.5 * m_eyeseparation * near_div_focallength;
1009                         switch(m_curreye)
1010                         {
1011                                 case RAS_STEREO_LEFTEYE:
1012                                                 left += offset;
1013                                                 right += offset;
1014                                                 break;
1015                                 case RAS_STEREO_RIGHTEYE:
1016                                                 left -= offset;
1017                                                 right -= offset;
1018                                                 break;
1019                         }
1020                         // leave bottom and top untouched
1021         }
1022         
1023         glMatrixMode(GL_PROJECTION);
1024         glLoadIdentity();
1025         glFrustum(left, right, bottom, top, frustnear, frustfar);
1026                 
1027         glGetDoublev(GL_PROJECTION_MATRIX, mat);
1028         result.setValue(mat);
1029
1030         return result;
1031 }
1032
1033 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
1034         float left,
1035         float right,
1036         float bottom,
1037         float top,
1038         float frustnear,
1039         float frustfar
1040 ) {
1041         MT_Matrix4x4 result;
1042         double mat[16];
1043
1044         // stereo is meaning less for orthographic, disable it
1045         glMatrixMode(GL_PROJECTION);
1046         glLoadIdentity();
1047         glOrtho(left, right, bottom, top, frustnear, frustfar);
1048                 
1049         glGetDoublev(GL_PROJECTION_MATRIX, mat);
1050         result.setValue(mat);
1051
1052         return result;
1053 }
1054
1055
1056 // next arguments probably contain redundant info, for later...
1057 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, 
1058                                                                                  const MT_Matrix3x3 & camOrientMat3x3,
1059                                                                                  const MT_Point3 & pos,
1060                                                                                  bool perspective)
1061 {
1062         m_viewmatrix = mat;
1063
1064         // correction for stereo
1065         if (Stereo() && perspective)
1066         {
1067                 MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
1068                 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
1069                 MT_Vector3 viewDir, viewupVec;
1070                 MT_Vector3 eyeline;
1071
1072                 // actual viewDir
1073                 viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
1074                 // actual viewup vec
1075                 viewupVec = camOrientMat3x3 * unitViewupVec;
1076
1077                 // vector between eyes
1078                 eyeline = viewDir.cross(viewupVec);
1079
1080                 switch(m_curreye)
1081                 {
1082                         case RAS_STEREO_LEFTEYE:
1083                                 {
1084                                 // translate to left by half the eye distance
1085                                 MT_Transform transform;
1086                                 transform.setIdentity();
1087                                 transform.translate(-(eyeline * m_eyeseparation / 2.0));
1088                                 m_viewmatrix *= transform;
1089                                 }
1090                                 break;
1091                         case RAS_STEREO_RIGHTEYE:
1092                                 {
1093                                 // translate to right by half the eye distance
1094                                 MT_Transform transform;
1095                                 transform.setIdentity();
1096                                 transform.translate(eyeline * m_eyeseparation / 2.0);
1097                                 m_viewmatrix *= transform;
1098                                 }
1099                                 break;
1100                 }
1101         }
1102
1103         m_viewinvmatrix = m_viewmatrix;
1104         m_viewinvmatrix.invert();
1105
1106         // note: getValue gives back column major as needed by OpenGL
1107         MT_Scalar glviewmat[16];
1108         m_viewmatrix.getValue(glviewmat);
1109
1110         glMatrixMode(GL_MODELVIEW);
1111         glLoadMatrixd(glviewmat);
1112         m_campos = pos;
1113 }
1114
1115
1116 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
1117 {
1118         return m_campos;
1119 }
1120
1121 bool RAS_OpenGLRasterizer::GetCameraOrtho()
1122 {
1123         return m_camortho;
1124 }
1125
1126 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
1127 {
1128         if (enable)
1129                 glEnable(GL_CULL_FACE);
1130         else
1131                 glDisable(GL_CULL_FACE);
1132 }
1133
1134 void RAS_OpenGLRasterizer::SetLines(bool enable)
1135 {
1136         if (enable)
1137                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1138         else
1139                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1140 }
1141
1142 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
1143                                                                                   float specY,
1144                                                                                   float specZ,
1145                                                                                   float specval)
1146 {
1147         GLfloat mat_specular[] = {specX, specY, specZ, specval};
1148         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1149 }
1150
1151
1152
1153 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
1154 {
1155         GLfloat mat_shininess[] = {     shiny };
1156         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1157 }
1158
1159
1160
1161 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
1162 {
1163         GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
1164         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
1165 }
1166
1167 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
1168 {
1169         GLfloat mat_emit [] = {eX,eY,eZ,e};
1170         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
1171 }
1172
1173
1174 double RAS_OpenGLRasterizer::GetTime()
1175 {
1176         return m_time;
1177 }
1178
1179 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
1180 {
1181         glPolygonOffset(mult, add);
1182         GLint mode = GL_POLYGON_OFFSET_FILL;
1183         if (m_drawingmode < KX_SHADED)
1184                 mode = GL_POLYGON_OFFSET_LINE;
1185         if (mult != 0.0f || add != 0.0f)
1186                 glEnable(mode);
1187         else
1188                 glDisable(mode);
1189 }
1190
1191 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
1192 {
1193         /* don't just set m_motionblur to 1, but check if it is 0 so
1194          * we don't reset a motion blur that is already enabled */
1195         if (m_motionblur == 0)
1196                 m_motionblur = 1;
1197         m_motionblurvalue = motionblurvalue;
1198 }
1199
1200 void RAS_OpenGLRasterizer::DisableMotionBlur()
1201 {
1202         m_motionblur = 0;
1203         m_motionblurvalue = -1.0;
1204 }
1205
1206 void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend)
1207 {
1208         GPU_set_material_alpha_blend(alphablend);
1209 /*
1210         if (alphablend == m_last_alphablend)
1211                 return;
1212
1213         if (alphablend == GPU_BLEND_SOLID) {
1214                 glDisable(GL_BLEND);
1215                 glDisable(GL_ALPHA_TEST);
1216                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1217         }
1218         else if (alphablend == GPU_BLEND_ADD) {
1219                 glBlendFunc(GL_ONE, GL_ONE);
1220                 glEnable(GL_BLEND);
1221                 glDisable(GL_ALPHA_TEST);
1222         }
1223         else if (alphablend == GPU_BLEND_ALPHA) {
1224                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1225                 glEnable(GL_BLEND);
1226                 glEnable(GL_ALPHA_TEST);
1227                 glAlphaFunc(GL_GREATER, 0.0f);
1228         }
1229         else if (alphablend == GPU_BLEND_CLIP) {
1230                 glDisable(GL_BLEND); 
1231                 glEnable(GL_ALPHA_TEST);
1232                 glAlphaFunc(GL_GREATER, 0.5f);
1233         }
1234
1235         m_last_alphablend = alphablend;
1236 */
1237 }
1238
1239 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
1240 {
1241         if (m_last_frontface == ccw)
1242                 return;
1243
1244         if (ccw)
1245                 glFrontFace(GL_CCW);
1246         else
1247                 glFrontFace(GL_CW);
1248         
1249         m_last_frontface = ccw;
1250 }
1251
1252 void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level)
1253 {
1254         GPU_set_anisotropic((float)level);
1255 }
1256
1257 short RAS_OpenGLRasterizer::GetAnisotropicFiltering()
1258 {
1259         return (short)GPU_get_anisotropic();
1260 }