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