Blender V2.61 - r43446

RAS_OpenGLRasterizer.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <math.h>
00034 #include <stdlib.h>
00035  
00036 #include "RAS_OpenGLRasterizer.h"
00037 
00038 #include "GL/glew.h"
00039 
00040 #include "RAS_Rect.h"
00041 #include "RAS_TexVert.h"
00042 #include "RAS_MeshObject.h"
00043 #include "MT_CmMatrix4x4.h"
00044 #include "RAS_IRenderTools.h" // rendering text
00045 
00046 #include "GPU_draw.h"
00047 #include "GPU_material.h"
00048 #include "GPU_extensions.h"
00049 
00050 #include "DNA_image_types.h"
00051 #include "DNA_meshdata_types.h"
00052 #include "DNA_material_types.h"
00053 #include "DNA_scene_types.h"
00054 
00055 #include "BKE_DerivedMesh.h"
00056 
00057 #ifndef M_PI
00058 #define M_PI        3.14159265358979323846
00059 #endif
00060 
00064 static GLuint left_eye_vinterlace_mask[32];
00065 static GLuint right_eye_vinterlace_mask[32];
00066 
00072 static GLuint hinterlace_mask[33];
00073 
00074 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
00075     :RAS_IRasterizer(canvas),
00076     m_2DCanvas(canvas),
00077     m_fogenabled(false),
00078     m_time(0.0),
00079     m_campos(0.0f, 0.0f, 0.0f),
00080     m_camortho(false),
00081     m_stereomode(RAS_STEREO_NOSTEREO),
00082     m_curreye(RAS_STEREO_LEFTEYE),
00083     m_eyeseparation(0.0),
00084     m_focallength(0.0),
00085     m_setfocallength(false),
00086     m_noOfScanlines(32),
00087     m_motionblur(0),
00088     m_motionblurvalue(-1.0),
00089     m_texco_num(0),
00090     m_attrib_num(0),
00091     //m_last_alphablend(GPU_BLEND_SOLID),
00092     m_last_frontface(true),
00093     m_materialCachingInfo(0)
00094 {
00095     m_viewmatrix.setIdentity();
00096     m_viewinvmatrix.setIdentity();
00097     
00098     for (int i = 0; i < 32; i++)
00099     {
00100         left_eye_vinterlace_mask[i] = 0x55555555;
00101         right_eye_vinterlace_mask[i] = 0xAAAAAAAA;
00102         hinterlace_mask[i] = (i&1)*0xFFFFFFFF;
00103     }
00104     hinterlace_mask[32] = 0;
00105 
00106     m_prevafvalue = GPU_get_anisotropic();
00107 }
00108 
00109 
00110 
00111 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
00112 {
00113     // Restore the previous AF value
00114     GPU_set_anisotropic(m_prevafvalue);
00115 }
00116 
00117 bool RAS_OpenGLRasterizer::Init()
00118 {
00119     GPU_state_init();
00120 
00121 
00122     m_ambr = 0.0f;
00123     m_ambg = 0.0f;
00124     m_ambb = 0.0f;
00125 
00126     glDisable(GL_BLEND);
00127     glDisable(GL_ALPHA_TEST);
00128     //m_last_alphablend = GPU_BLEND_SOLID;
00129     GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
00130 
00131     glFrontFace(GL_CCW);
00132     m_last_frontface = true;
00133 
00134     m_redback = 0.4375;
00135     m_greenback = 0.4375;
00136     m_blueback = 0.4375;
00137     m_alphaback = 0.0;
00138 
00139     glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
00140     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00141     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00142 
00143 
00144     glShadeModel(GL_SMOOTH);
00145 
00146     return true;
00147 }
00148 
00149 
00150 void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue)
00151 {
00152     m_ambr = red;
00153     m_ambg = green;
00154     m_ambb = blue;
00155 }
00156 
00157 
00158 void RAS_OpenGLRasterizer::SetAmbient(float factor)
00159 {
00160     float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f };
00161     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
00162 }
00163 
00164 
00165 void RAS_OpenGLRasterizer::SetBackColor(float red,
00166                                         float green,
00167                                         float blue,
00168                                         float alpha)
00169 {
00170     m_redback = red;
00171     m_greenback = green;
00172     m_blueback = blue;
00173     m_alphaback = alpha;
00174 }
00175 
00176 
00177 
00178 void RAS_OpenGLRasterizer::SetFogColor(float r,
00179                                        float g,
00180                                        float b)
00181 {
00182     m_fogr = r;
00183     m_fogg = g;
00184     m_fogb = b;
00185     m_fogenabled = true;
00186 }
00187 
00188 
00189 
00190 void RAS_OpenGLRasterizer::SetFogStart(float start)
00191 {
00192     m_fogstart = start;
00193     m_fogenabled = true;
00194 }
00195 
00196 
00197 
00198 void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
00199 {
00200     m_fogdist = fogend;
00201     m_fogenabled = true;
00202 }
00203 
00204 
00205 
00206 void RAS_OpenGLRasterizer::SetFog(float start,
00207                                   float dist,
00208                                   float r,
00209                                   float g,
00210                                   float b)
00211 {
00212     m_fogstart = start;
00213     m_fogdist = dist;
00214     m_fogr = r;
00215     m_fogg = g;
00216     m_fogb = b;
00217     m_fogenabled = true;
00218 }
00219 
00220 
00221 
00222 void RAS_OpenGLRasterizer::DisableFog()
00223 {
00224     m_fogenabled = false;
00225 }
00226 
00227 bool RAS_OpenGLRasterizer::IsFogEnabled()
00228 {
00229     return m_fogenabled;
00230 }
00231 
00232 
00233 void RAS_OpenGLRasterizer::DisplayFog()
00234 {
00235     if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
00236     {
00237         float params[5];
00238         glFogi(GL_FOG_MODE, GL_LINEAR);
00239         glFogf(GL_FOG_DENSITY, 0.1f);
00240         glFogf(GL_FOG_START, m_fogstart);
00241         glFogf(GL_FOG_END, m_fogstart + m_fogdist);
00242         params[0]= m_fogr;
00243         params[1]= m_fogg;
00244         params[2]= m_fogb;
00245         params[3]= 0.0;
00246         glFogfv(GL_FOG_COLOR, params); 
00247         glEnable(GL_FOG);
00248     } 
00249     else
00250     {
00251         glDisable(GL_FOG);
00252     }
00253 }
00254 
00255 
00256 
00257 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
00258 {
00259     return mat.Activate(this, m_materialCachingInfo);
00260 }
00261 
00262 
00263 
00264 void RAS_OpenGLRasterizer::Exit()
00265 {
00266 
00267     glEnable(GL_CULL_FACE);
00268     glEnable(GL_DEPTH_TEST);
00269     glClearDepth(1.0); 
00270     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00271     glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
00272     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00273     glDepthMask (GL_TRUE);
00274     glDepthFunc(GL_LEQUAL);
00275     glBlendFunc(GL_ONE, GL_ZERO);
00276     
00277     glDisable(GL_POLYGON_STIPPLE);
00278     
00279     glDisable(GL_LIGHTING);
00280     if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
00281         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
00282     
00283     EndFrame();
00284 }
00285 
00286 bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
00287 {
00288     m_time = time;
00289     m_drawingmode = drawingmode;
00290 
00291     // Blender camera routine destroys the settings
00292     if (m_drawingmode < KX_SOLID)
00293     {
00294         glDisable (GL_CULL_FACE);
00295         glDisable (GL_DEPTH_TEST);
00296     }
00297     else
00298     {
00299         glEnable(GL_DEPTH_TEST);
00300         glEnable (GL_CULL_FACE);
00301     }
00302 
00303     glDisable(GL_BLEND);
00304     glDisable(GL_ALPHA_TEST);
00305     //m_last_alphablend = GPU_BLEND_SOLID;
00306     GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
00307 
00308     glFrontFace(GL_CCW);
00309     m_last_frontface = true;
00310 
00311     glShadeModel(GL_SMOOTH);
00312 
00313     glEnable(GL_MULTISAMPLE_ARB);
00314 
00315     m_2DCanvas->BeginFrame();
00316     
00317     return true;
00318 }
00319 
00320 
00321 
00322 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
00323 {
00324     m_drawingmode = drawingmode;
00325 
00326     if(m_drawingmode == KX_WIREFRAME)
00327         glDisable(GL_CULL_FACE);
00328 }
00329 
00330 int RAS_OpenGLRasterizer::GetDrawingMode()
00331 {
00332     return m_drawingmode;
00333 }
00334 
00335 
00336 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
00337 {
00338     glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
00339 }
00340 
00341 
00342 void RAS_OpenGLRasterizer::ClearColorBuffer()
00343 {
00344     m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
00345     m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
00346 }
00347 
00348 
00349 void RAS_OpenGLRasterizer::ClearDepthBuffer()
00350 {
00351     m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
00352 }
00353 
00354 
00355 void RAS_OpenGLRasterizer::ClearCachingInfo(void)
00356 {
00357     m_materialCachingInfo = 0;
00358 }
00359 
00360 void RAS_OpenGLRasterizer::FlushDebugShapes()
00361 {
00362     if(!m_debugShapes.size())
00363         return;
00364 
00365     // DrawDebugLines
00366     GLboolean light, tex;
00367 
00368     light= glIsEnabled(GL_LIGHTING);
00369     tex= glIsEnabled(GL_TEXTURE_2D);
00370 
00371     if(light) glDisable(GL_LIGHTING);
00372     if(tex) glDisable(GL_TEXTURE_2D);
00373 
00374     //draw lines
00375     glBegin(GL_LINES);
00376     for (unsigned int i=0;i<m_debugShapes.size();i++)
00377     {
00378         if (m_debugShapes[i].m_type != OglDebugShape::LINE)
00379             continue;
00380         glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
00381         const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x();
00382         const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x();
00383         glVertex3dv(fromPtr);
00384         glVertex3dv(toPtr);
00385     }
00386     glEnd();
00387 
00388     //draw circles
00389     for (unsigned int i=0;i<m_debugShapes.size();i++)
00390     {
00391         if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE)
00392             continue;
00393         glBegin(GL_LINE_LOOP);
00394         glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
00395 
00396         static const MT_Vector3 worldUp(0.,0.,1.);
00397         MT_Vector3 norm = m_debugShapes[i].m_param;
00398         MT_Matrix3x3 tr;
00399         if (norm.fuzzyZero() || norm == worldUp)
00400         {
00401             tr.setIdentity();
00402         }
00403         else
00404         {
00405             MT_Vector3 xaxis, yaxis;
00406             xaxis = MT_cross(norm, worldUp);
00407             yaxis = MT_cross(xaxis, norm);
00408             tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(),
00409                 yaxis.x(), yaxis.y(), yaxis.z(),
00410                 norm.x(), norm.y(), norm.z());
00411         }
00412         MT_Scalar rad = m_debugShapes[i].m_param2.x();
00413         int n = (int) m_debugShapes[i].m_param2.y();
00414         for (int j = 0; j<n; j++)
00415         {
00416             MT_Scalar theta = j*M_PI*2/n;
00417             MT_Vector3 pos(cos(theta)*rad, sin(theta)*rad, 0.);
00418             pos = pos*tr;
00419             pos += m_debugShapes[i].m_pos;
00420             const MT_Scalar* posPtr = &pos.x();
00421             glVertex3dv(posPtr);
00422         }
00423         glEnd();
00424     }
00425 
00426     if(light) glEnable(GL_LIGHTING);
00427     if(tex) glEnable(GL_TEXTURE_2D);
00428 
00429     m_debugShapes.clear();
00430 }
00431 
00432 void RAS_OpenGLRasterizer::EndFrame()
00433 {
00434     FlushDebugShapes();
00435 
00436     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00437 
00438     glDisable(GL_MULTISAMPLE_ARB);
00439 
00440     m_2DCanvas->EndFrame();
00441 }   
00442 
00443 void RAS_OpenGLRasterizer::SetRenderArea()
00444 {
00445     RAS_Rect area;
00446     // only above/below stereo method needs viewport adjustment
00447     switch (m_stereomode)
00448     {
00449         case RAS_STEREO_ABOVEBELOW:
00450             switch(m_curreye)
00451             {
00452                 case RAS_STEREO_LEFTEYE:
00453                     // upper half of window
00454                     area.SetLeft(0);
00455                     area.SetBottom(m_2DCanvas->GetHeight() -
00456                         int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
00457     
00458                     area.SetRight(int(m_2DCanvas->GetWidth()));
00459                     area.SetTop(int(m_2DCanvas->GetHeight()));
00460                     m_2DCanvas->SetDisplayArea(&area);
00461                     break;
00462                 case RAS_STEREO_RIGHTEYE:
00463                     // lower half of window
00464                     area.SetLeft(0);
00465                     area.SetBottom(0);
00466                     area.SetRight(int(m_2DCanvas->GetWidth()));
00467                     area.SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
00468                     m_2DCanvas->SetDisplayArea(&area);
00469                     break;
00470             }
00471             break;
00472         case RAS_STEREO_SIDEBYSIDE:
00473             switch (m_curreye)
00474             {
00475                 case RAS_STEREO_LEFTEYE:
00476                     // Left half of window
00477                     area.SetLeft(0);
00478                     area.SetBottom(0);
00479                     area.SetRight(m_2DCanvas->GetWidth()/2);
00480                     area.SetTop(m_2DCanvas->GetHeight());
00481                     m_2DCanvas->SetDisplayArea(&area);
00482                     break;
00483                 case RAS_STEREO_RIGHTEYE:
00484                     // Right half of window
00485                     area.SetLeft(m_2DCanvas->GetWidth()/2);
00486                     area.SetBottom(0);
00487                     area.SetRight(m_2DCanvas->GetWidth());
00488                     area.SetTop(m_2DCanvas->GetHeight());
00489                     m_2DCanvas->SetDisplayArea(&area);
00490                     break;
00491             }
00492             break;
00493         default:
00494             // every available pixel
00495             area.SetLeft(0);
00496             area.SetBottom(0);
00497             area.SetRight(int(m_2DCanvas->GetWidth()));
00498             area.SetTop(int(m_2DCanvas->GetHeight()));
00499             m_2DCanvas->SetDisplayArea(&area);
00500             break;
00501     }
00502 }
00503     
00504 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
00505 {
00506     m_stereomode = stereomode;
00507 }
00508 
00509 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
00510 {
00511     return m_stereomode;
00512 }
00513 
00514 bool RAS_OpenGLRasterizer::Stereo()
00515 {
00516     if(m_stereomode > RAS_STEREO_NOSTEREO) // > 0
00517         return true;
00518     else
00519         return false;
00520 }
00521 
00522 bool RAS_OpenGLRasterizer::InterlacedStereo()
00523 {
00524     return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
00525 }
00526 
00527 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
00528 {
00529     m_curreye = eye;
00530     switch (m_stereomode)
00531     {
00532         case RAS_STEREO_QUADBUFFERED:
00533             glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
00534             break;
00535         case RAS_STEREO_ANAGLYPH:
00536             if (m_curreye == RAS_STEREO_LEFTEYE)
00537             {
00538                 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
00539             } else {
00540                 //glAccum(GL_LOAD, 1.0);
00541                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
00542                 ClearDepthBuffer();
00543             }
00544             break;
00545         case RAS_STEREO_VINTERLACE:
00546         {
00547             glEnable(GL_POLYGON_STIPPLE);
00548             glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
00549             if (m_curreye == RAS_STEREO_RIGHTEYE)
00550                 ClearDepthBuffer();
00551             break;
00552         }
00553         case RAS_STEREO_INTERLACED:
00554         {
00555             glEnable(GL_POLYGON_STIPPLE);
00556             glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
00557             if (m_curreye == RAS_STEREO_RIGHTEYE)
00558                 ClearDepthBuffer();
00559             break;
00560         }
00561         default:
00562             break;
00563     }
00564 }
00565 
00566 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
00567 {
00568     return m_curreye;
00569 }
00570 
00571 
00572 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
00573 {
00574     m_eyeseparation = eyeseparation;
00575 }
00576 
00577 float RAS_OpenGLRasterizer::GetEyeSeparation()
00578 {
00579     return m_eyeseparation;
00580 }
00581 
00582 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
00583 {
00584     m_focallength = focallength;
00585     m_setfocallength = true;
00586 }
00587 
00588 float RAS_OpenGLRasterizer::GetFocalLength()
00589 {
00590     return m_focallength;
00591 }
00592 
00593 
00594 void RAS_OpenGLRasterizer::SwapBuffers()
00595 {
00596     m_2DCanvas->SwapBuffers();
00597 }
00598 
00599 
00600 
00601 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
00602 {
00603     return m_viewmatrix;
00604 }
00605 
00606 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
00607 {
00608     return m_viewinvmatrix;
00609 }
00610 
00611 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
00612                                     class RAS_IPolyMaterial* polymat,
00613                                     class RAS_IRenderTools* rendertools)
00614 { 
00615     bool obcolor = ms.m_bObjectColor;
00616     MT_Vector4& rgba = ms.m_RGBAcolor;
00617     RAS_MeshSlot::iterator it;
00618 
00619     // handle object color
00620     if (obcolor) {
00621         glDisableClientState(GL_COLOR_ARRAY);
00622         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00623     }
00624     else
00625         glEnableClientState(GL_COLOR_ARRAY);
00626 
00627     for(ms.begin(it); !ms.end(it); ms.next(it)) {
00628         RAS_TexVert *vertex;
00629         size_t i, j, numvert;
00630         
00631         numvert = it.array->m_type;
00632 
00633         if(it.array->m_type == RAS_DisplayArray::LINE) {
00634             // line drawing, no text
00635             glBegin(GL_LINES);
00636 
00637             for(i=0; i<it.totindex; i+=2)
00638             {
00639                 vertex = &it.vertex[it.index[i]];
00640                 glVertex3fv(vertex->getXYZ());
00641 
00642                 vertex = &it.vertex[it.index[i+1]];
00643                 glVertex3fv(vertex->getXYZ());
00644             }
00645 
00646             glEnd();
00647         }
00648         else {
00649             // triangle and quad text drawing
00650             for(i=0; i<it.totindex; i+=numvert)
00651             {
00652                 float v[4][3];
00653                 int glattrib, unit;
00654 
00655                 for(j=0; j<numvert; j++) {
00656                     vertex = &it.vertex[it.index[i+j]];
00657 
00658                     v[j][0] = vertex->getXYZ()[0];
00659                     v[j][1] = vertex->getXYZ()[1];
00660                     v[j][2] = vertex->getXYZ()[2];
00661                 }
00662 
00663                 // find the right opengl attribute
00664                 glattrib = -1;
00665                 if(GLEW_ARB_vertex_program)
00666                     for(unit=0; unit<m_attrib_num; unit++)
00667                         if(m_attrib[unit] == RAS_TEXCO_UV1)
00668                             glattrib = unit;
00669                 
00670                 rendertools->RenderText(polymat->GetDrawingMode(), polymat,
00671                     v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib);
00672 
00673                 ClearCachingInfo();
00674             }
00675         }
00676     }
00677 
00678     glDisableClientState(GL_COLOR_ARRAY);
00679 }
00680 
00681 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
00682 {
00683     m_texco_num = num;
00684     if(m_texco_num > RAS_MAX_TEXCO)
00685         m_texco_num = RAS_MAX_TEXCO;
00686 }
00687 
00688 void RAS_OpenGLRasterizer::SetAttribNum(int num)
00689 {
00690     m_attrib_num = num;
00691     if(m_attrib_num > RAS_MAX_ATTRIB)
00692         m_attrib_num = RAS_MAX_ATTRIB;
00693 }
00694 
00695 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
00696 {
00697     // this changes from material to material
00698     if(unit < RAS_MAX_TEXCO)
00699         m_texco[unit] = coords;
00700 }
00701 
00702 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit)
00703 {
00704     // this changes from material to material
00705     if(unit < RAS_MAX_ATTRIB)
00706         m_attrib[unit] = coords;
00707 }
00708 
00709 void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
00710 {
00711     int unit;
00712 
00713     if(GLEW_ARB_multitexture) {
00714         for(unit=0; unit<m_texco_num; unit++) {
00715             if(tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
00716                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
00717                 continue;
00718             }
00719             switch(m_texco[unit]) {
00720             case RAS_TEXCO_ORCO:
00721             case RAS_TEXCO_GLOB:
00722                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
00723                 break;
00724             case RAS_TEXCO_UV1:
00725                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
00726                 break;
00727             case RAS_TEXCO_NORM:
00728                 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal());
00729                 break;
00730             case RAS_TEXTANGENT:
00731                 glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent());
00732                 break;
00733             case RAS_TEXCO_UV2:
00734                 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
00735                 break;
00736             default:
00737                 break;
00738             }
00739         }
00740     }
00741 
00742     if(GLEW_ARB_vertex_program) {
00743         for(unit=0; unit<m_attrib_num; unit++) {
00744             switch(m_attrib[unit]) {
00745             case RAS_TEXCO_ORCO:
00746             case RAS_TEXCO_GLOB:
00747                 glVertexAttrib3fvARB(unit, tv.getXYZ());
00748                 break;
00749             case RAS_TEXCO_UV1:
00750                 glVertexAttrib2fvARB(unit, tv.getUV1());
00751                 break;
00752             case RAS_TEXCO_NORM:
00753                 glVertexAttrib3fvARB(unit, tv.getNormal());
00754                 break;
00755             case RAS_TEXTANGENT:
00756                 glVertexAttrib4fvARB(unit, tv.getTangent());
00757                 break;
00758             case RAS_TEXCO_UV2:
00759                 glVertexAttrib2fvARB(unit, tv.getUV2());
00760                 break;
00761             case RAS_TEXCO_VCOL:
00762                 glVertexAttrib4ubvARB(unit, tv.getRGBA());
00763                 break;
00764             default:
00765                 break;
00766             }
00767         }
00768     }
00769 
00770 }
00771 
00772 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
00773 {
00774     IndexPrimitivesInternal(ms, false);
00775 }
00776 
00777 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
00778 {
00779     IndexPrimitivesInternal(ms, true);
00780 }
00781 
00782 static bool current_wireframe;
00783 static RAS_MaterialBucket *current_bucket;
00784 static RAS_IPolyMaterial *current_polymat;
00785 static RAS_MeshSlot *current_ms;
00786 static RAS_MeshObject *current_mesh;
00787 static int current_blmat_nr;
00788 static GPUVertexAttribs current_gpu_attribs;
00789 static Image *current_image;
00790 static int CheckMaterialDM(int matnr, void *attribs)
00791 {
00792     // only draw the current material
00793     if (matnr != current_blmat_nr)
00794         return 0;
00795     GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
00796     if (gattribs)
00797         memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
00798     return 1;
00799 }
00800 
00801 /*
00802 static int CheckTexfaceDM(void *mcol, int index)
00803 {
00804 
00805     // index is the original face index, retrieve the polygon
00806     RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
00807         current_mesh->GetPolygon(index) : NULL;
00808     if (polygon && polygon->GetMaterial() == current_bucket) {
00809         // must handle color.
00810         if (current_wireframe)
00811             return 2;
00812         if (current_ms->m_bObjectColor) {
00813             MT_Vector4& rgba = current_ms->m_RGBAcolor;
00814             glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00815             // don't use mcol
00816             return 2;
00817         }
00818         if (!mcol) {
00819             // we have to set the color from the material
00820             unsigned char rgba[4];
00821             current_polymat->GetMaterialRGBAColor(rgba);
00822             glColor4ubv((const GLubyte *)rgba);
00823             return 2;
00824         }
00825         return 1;
00826     }
00827     return 0;
00828 }
00829 */
00830 
00831 static int CheckTexDM(MTFace *tface, int has_mcol, int matnr)
00832 {
00833 
00834     // index is the original face index, retrieve the polygon
00835     if (matnr == current_blmat_nr &&
00836         (tface == NULL || tface->tpage == current_image)) {
00837         // must handle color.
00838         if (current_wireframe)
00839             return 2;
00840         if (current_ms->m_bObjectColor) {
00841             MT_Vector4& rgba = current_ms->m_RGBAcolor;
00842             glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00843             // don't use mcol
00844             return 2;
00845         }
00846         if (!has_mcol) {
00847             // we have to set the color from the material
00848             unsigned char rgba[4];
00849             current_polymat->GetMaterialRGBAColor(rgba);
00850             glColor4ubv((const GLubyte *)rgba);
00851             return 2;
00852         }
00853         return 1;
00854     }
00855     return 0;
00856 }
00857 
00858 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
00859 { 
00860     bool obcolor = ms.m_bObjectColor;
00861     bool wireframe = m_drawingmode <= KX_WIREFRAME;
00862     MT_Vector4& rgba = ms.m_RGBAcolor;
00863     RAS_MeshSlot::iterator it;
00864 
00865     if (ms.m_pDerivedMesh) {
00866         // mesh data is in derived mesh, 
00867         current_bucket = ms.m_bucket;
00868         current_polymat = current_bucket->GetPolyMaterial();
00869         current_ms = &ms;
00870         current_mesh = ms.m_mesh;
00871         current_wireframe = wireframe;
00872         // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
00873 
00874         // handle two-side
00875         if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
00876             this->SetCullFace(true);
00877         else
00878             this->SetCullFace(false);
00879 
00880         if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
00881             // GetMaterialIndex return the original mface material index, 
00882             // increment by 1 to match what derived mesh is doing
00883             current_blmat_nr = current_polymat->GetMaterialIndex()+1;
00884             // For GLSL we need to retrieve the GPU material attribute
00885             Material* blmat = current_polymat->GetBlenderMaterial();
00886             Scene* blscene = current_polymat->GetBlenderScene();
00887             if (!wireframe && blscene && blmat)
00888                 GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), &current_gpu_attribs);
00889             else
00890                 memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
00891             // DM draw can mess up blending mode, restore at the end
00892             int current_blend_mode = GPU_get_material_alpha_blend();
00893             ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
00894             GPU_set_material_alpha_blend(current_blend_mode);
00895         } else {
00896             //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
00897             current_blmat_nr = current_polymat->GetMaterialIndex();
00898             current_image = current_polymat->GetBlenderImage();
00899             ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL);
00900         }
00901         return;
00902     }
00903     // iterate over display arrays, each containing an index + vertex array
00904     for(ms.begin(it); !ms.end(it); ms.next(it)) {
00905         RAS_TexVert *vertex;
00906         size_t i, j, numvert;
00907         
00908         numvert = it.array->m_type;
00909 
00910         if(it.array->m_type == RAS_DisplayArray::LINE) {
00911             // line drawing
00912             glBegin(GL_LINES);
00913 
00914             for(i=0; i<it.totindex; i+=2)
00915             {
00916                 vertex = &it.vertex[it.index[i]];
00917                 glVertex3fv(vertex->getXYZ());
00918 
00919                 vertex = &it.vertex[it.index[i+1]];
00920                 glVertex3fv(vertex->getXYZ());
00921             }
00922 
00923             glEnd();
00924         }
00925         else {
00926             // triangle and quad drawing
00927             if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
00928                 glBegin(GL_TRIANGLES);
00929             else
00930                 glBegin(GL_QUADS);
00931 
00932             for(i=0; i<it.totindex; i+=numvert)
00933             {
00934                 if(obcolor)
00935                     glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00936 
00937                 for(j=0; j<numvert; j++) {
00938                     vertex = &it.vertex[it.index[i+j]];
00939 
00940                     if(!wireframe) {
00941                         if(!obcolor)
00942                             glColor4ubv((const GLubyte *)(vertex->getRGBA()));
00943 
00944                         glNormal3fv(vertex->getNormal());
00945 
00946                         if(multi)
00947                             TexCoord(*vertex);
00948                         else
00949                             glTexCoord2fv(vertex->getUV1());
00950                     }
00951 
00952                     glVertex3fv(vertex->getXYZ());
00953                 }
00954             }
00955 
00956             glEnd();
00957         }
00958     }
00959 }
00960 
00961 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
00962 {
00963     glMatrixMode(GL_PROJECTION);
00964     double* matrix = &mat(0,0);
00965     glLoadMatrixd(matrix);
00966 
00967     m_camortho= (mat(3, 3) != 0.0f);
00968 }
00969 
00970 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
00971 {
00972     glMatrixMode(GL_PROJECTION);
00973     double matrix[16];
00974     /* Get into argument. Looks a bit dodgy, but it's ok. */
00975     mat.getValue(matrix);
00976     /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
00977     glLoadMatrixd(matrix);  
00978 
00979     m_camortho= (mat[3][3] != 0.0f);
00980 }
00981 
00982 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
00983     float left,
00984     float right,
00985     float bottom,
00986     float top,
00987     float frustnear,
00988     float frustfar,
00989     float focallength,
00990     bool 
00991 ){
00992     MT_Matrix4x4 result;
00993     double mat[16];
00994 
00995     // correction for stereo
00996     if(Stereo())
00997     {
00998             float near_div_focallength;
00999             float offset;
01000 
01001             // if Rasterizer.setFocalLength is not called we use the camera focallength
01002             if (!m_setfocallength)
01003                 // if focallength is null we use a value known to be reasonable
01004                 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0
01005                     : focallength;
01006 
01007             near_div_focallength = frustnear / m_focallength;
01008             offset = 0.5 * m_eyeseparation * near_div_focallength;
01009             switch(m_curreye)
01010             {
01011                 case RAS_STEREO_LEFTEYE:
01012                         left += offset;
01013                         right += offset;
01014                         break;
01015                 case RAS_STEREO_RIGHTEYE:
01016                         left -= offset;
01017                         right -= offset;
01018                         break;
01019             }
01020             // leave bottom and top untouched
01021     }
01022     
01023     glMatrixMode(GL_PROJECTION);
01024     glLoadIdentity();
01025     glFrustum(left, right, bottom, top, frustnear, frustfar);
01026         
01027     glGetDoublev(GL_PROJECTION_MATRIX, mat);
01028     result.setValue(mat);
01029 
01030     return result;
01031 }
01032 
01033 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
01034     float left,
01035     float right,
01036     float bottom,
01037     float top,
01038     float frustnear,
01039     float frustfar
01040 ){
01041     MT_Matrix4x4 result;
01042     double mat[16];
01043 
01044     // stereo is meaning less for orthographic, disable it
01045     glMatrixMode(GL_PROJECTION);
01046     glLoadIdentity();
01047     glOrtho(left, right, bottom, top, frustnear, frustfar);
01048         
01049     glGetDoublev(GL_PROJECTION_MATRIX, mat);
01050     result.setValue(mat);
01051 
01052     return result;
01053 }
01054 
01055 
01056 // next arguments probably contain redundant info, for later...
01057 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, 
01058                                          const MT_Matrix3x3 & camOrientMat3x3,
01059                                          const MT_Point3 & pos,
01060                                          bool perspective)
01061 {
01062     m_viewmatrix = mat;
01063 
01064     // correction for stereo
01065     if(Stereo() && perspective)
01066     {
01067         MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
01068         MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
01069         MT_Vector3 viewDir, viewupVec;
01070         MT_Vector3 eyeline;
01071 
01072         // actual viewDir
01073         viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
01074         // actual viewup vec
01075         viewupVec = camOrientMat3x3 * unitViewupVec;
01076 
01077         // vector between eyes
01078         eyeline = viewDir.cross(viewupVec);
01079 
01080         switch(m_curreye)
01081         {
01082             case RAS_STEREO_LEFTEYE:
01083                 {
01084                 // translate to left by half the eye distance
01085                 MT_Transform transform;
01086                 transform.setIdentity();
01087                 transform.translate(-(eyeline * m_eyeseparation / 2.0));
01088                 m_viewmatrix *= transform;
01089                 }
01090                 break;
01091             case RAS_STEREO_RIGHTEYE:
01092                 {
01093                 // translate to right by half the eye distance
01094                 MT_Transform transform;
01095                 transform.setIdentity();
01096                 transform.translate(eyeline * m_eyeseparation / 2.0);
01097                 m_viewmatrix *= transform;
01098                 }
01099                 break;
01100         }
01101     }
01102 
01103     m_viewinvmatrix = m_viewmatrix;
01104     m_viewinvmatrix.invert();
01105 
01106     // note: getValue gives back column major as needed by OpenGL
01107     MT_Scalar glviewmat[16];
01108     m_viewmatrix.getValue(glviewmat);
01109 
01110     glMatrixMode(GL_MODELVIEW);
01111     glLoadMatrixd(glviewmat);
01112     m_campos = pos;
01113 }
01114 
01115 
01116 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
01117 {
01118     return m_campos;
01119 }
01120 
01121 bool RAS_OpenGLRasterizer::GetCameraOrtho()
01122 {
01123     return m_camortho;
01124 }
01125 
01126 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
01127 {
01128     if (enable)
01129         glEnable(GL_CULL_FACE);
01130     else
01131         glDisable(GL_CULL_FACE);
01132 }
01133 
01134 void RAS_OpenGLRasterizer::SetLines(bool enable)
01135 {
01136     if (enable)
01137         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01138     else
01139         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01140 }
01141 
01142 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
01143                                           float specY,
01144                                           float specZ,
01145                                           float specval)
01146 {
01147     GLfloat mat_specular[] = {specX, specY, specZ, specval};
01148     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
01149 }
01150 
01151 
01152 
01153 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
01154 {
01155     GLfloat mat_shininess[] = { shiny };
01156     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
01157 }
01158 
01159 
01160 
01161 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
01162 {
01163     GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
01164     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
01165 }
01166 
01167 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
01168 {
01169     GLfloat mat_emit [] = {eX,eY,eZ,e};
01170     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
01171 }
01172 
01173 
01174 double RAS_OpenGLRasterizer::GetTime()
01175 {
01176     return m_time;
01177 }
01178 
01179 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
01180 {
01181     glPolygonOffset(mult, add);
01182     GLint mode = GL_POLYGON_OFFSET_FILL;
01183     if (m_drawingmode < KX_SHADED)
01184         mode = GL_POLYGON_OFFSET_LINE;
01185     if (mult != 0.0f || add != 0.0f)
01186         glEnable(mode);
01187     else
01188         glDisable(mode);
01189 }
01190 
01191 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
01192 {
01193     /* don't just set m_motionblur to 1, but check if it is 0 so
01194      * we don't reset a motion blur that is already enabled */
01195     if(m_motionblur == 0)
01196         m_motionblur = 1;
01197     m_motionblurvalue = motionblurvalue;
01198 }
01199 
01200 void RAS_OpenGLRasterizer::DisableMotionBlur()
01201 {
01202     m_motionblur = 0;
01203     m_motionblurvalue = -1.0;
01204 }
01205 
01206 void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend)
01207 {
01208     GPU_set_material_alpha_blend(alphablend);
01209 /*
01210     if(alphablend == m_last_alphablend)
01211         return;
01212 
01213     if(alphablend == GPU_BLEND_SOLID) {
01214         glDisable(GL_BLEND);
01215         glDisable(GL_ALPHA_TEST);
01216         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01217     }
01218     else if(alphablend == GPU_BLEND_ADD) {
01219         glBlendFunc(GL_ONE, GL_ONE);
01220         glEnable(GL_BLEND);
01221         glDisable(GL_ALPHA_TEST);
01222     }
01223     else if(alphablend == GPU_BLEND_ALPHA) {
01224         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01225         glEnable(GL_BLEND);
01226         glEnable(GL_ALPHA_TEST);
01227         glAlphaFunc(GL_GREATER, 0.0f);
01228     }
01229     else if(alphablend == GPU_BLEND_CLIP) {
01230         glDisable(GL_BLEND); 
01231         glEnable(GL_ALPHA_TEST);
01232         glAlphaFunc(GL_GREATER, 0.5f);
01233     }
01234 
01235     m_last_alphablend = alphablend;
01236 */
01237 }
01238 
01239 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
01240 {
01241     if(m_last_frontface == ccw)
01242         return;
01243 
01244     if(ccw)
01245         glFrontFace(GL_CCW);
01246     else
01247         glFrontFace(GL_CW);
01248     
01249     m_last_frontface = ccw;
01250 }
01251 
01252 void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level)
01253 {
01254     GPU_set_anisotropic((float)level);
01255 }
01256 
01257 short RAS_OpenGLRasterizer::GetAnisotropicFiltering()
01258 {
01259     return (short)GPU_get_anisotropic();
01260 }