Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_VAOpenGLRasterizer.cpp
index ddfcc3f3f9dd109f9cc8499982d51a1401b648fc..c78a97ad7beec843be144685b04ff35abaa7ddae 100644 (file)
 #include "RAS_VAOpenGLRasterizer.h"
 #include <stdlib.h>
 
-#ifdef WIN32
-#include <windows.h>
-#endif // WIN32
-#ifdef __APPLE__
-#define GL_GLEXT_LEGACY 1
-#include <OpenGL/gl.h>
-#else
-#include <GL/gl.h>
-#endif
+#include "GL/glew.h"
 
 #include "STR_String.h"
 #include "RAS_TexVert.h"
 #include "MT_CmMatrix4x4.h"
 #include "RAS_IRenderTools.h" // rendering text
-
-#include "RAS_GLExtensionManager.h"
        
-
-using namespace bgl;
-
 RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock)
 :      RAS_OpenGLRasterizer(canvas),
-       m_Lock(lock && RAS_EXT_support._EXT_compiled_vertex_array)      
+       m_Lock(lock && GLEW_EXT_compiled_vertex_array),
+       m_last_texco_num(0),
+       m_last_attrib_num(0)
 {
 }
 
-
-
 RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
 {
 }
@@ -72,9 +59,9 @@ bool RAS_VAOpenGLRasterizer::Init(void)
        if (result)
        {
                glEnableClientState(GL_VERTEX_ARRAY);
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
                glEnableClientState(GL_NORMAL_ARRAY);
                glDisableClientState(GL_COLOR_ARRAY);
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        }
@@ -82,87 +69,59 @@ bool RAS_VAOpenGLRasterizer::Init(void)
        return result;
 }
 
-
-
 void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
 {
        m_drawingmode = drawingmode;
 
-               switch (m_drawingmode)
+       switch (m_drawingmode)
        {
-       case KX_BOUNDINGBOX:
-               {
-               }
-       case KX_WIREFRAME:
-               {
-                       glDisable (GL_CULL_FACE);
+               case KX_BOUNDINGBOX:
+               case KX_WIREFRAME:
+                       glDisableClientState(GL_COLOR_ARRAY);
+                       glDisable(GL_CULL_FACE);
                        break;
-               }
-       case KX_TEXTURED:
-               {
-               }
-       case KX_SHADED:
-               {
+               case KX_SOLID:
+                       glDisableClientState(GL_COLOR_ARRAY);
+                       break;
+               case KX_TEXTURED:
+               case KX_SHADED:
+               case KX_SHADOW:
                        glEnableClientState(GL_COLOR_ARRAY);
-               }
-       case KX_SOLID:
-               {
+               default:
                        break;
-               }
-       default:
-               {
-               }
        }
 }
 
-
-
 void RAS_VAOpenGLRasterizer::Exit()
 {
-       glDisableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_NORMAL_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
-       glDisableClientState(GL_NORMAL_ARRAY);
+       EnableTextures(false);
 
        RAS_OpenGLRasterizer::Exit();
 }
 
-
-
 void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays,
                                                        const vecIndexArrays & indexarrays,
-                                                       int mode,
-                                                       class RAS_IPolyMaterial* polymat,
-                                                       class RAS_IRenderTools* rendertools,
+                                                       DrawMode mode,
                                                        bool useObjectColor,
                                                        const MT_Vector4& rgbacolor,
                                                        class KX_ListSlot** slot)
 {
        static const GLsizei vtxstride = sizeof(RAS_TexVert);
        GLenum drawmode;
-       switch (mode)
-       {
-       case 0:
-               {
+       if(mode == KX_MODE_TRIANGLES)
                drawmode = GL_TRIANGLES;
-               break;
-               }
-       case 2:
-               {
+       else if(mode == KX_MODE_QUADS)
                drawmode = GL_QUADS;
-               break;
-               }
-       case 1: //lines
-               {
-               }
-       default:
-               {
+       else
                drawmode = GL_LINES;
-               break;
-               }
-       }
+
        const RAS_TexVert* vertexarray;
        unsigned int numindices, vt;
+
        if (drawmode != GL_LINES)
        {
                if (useObjectColor)
@@ -180,6 +139,9 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays
                glColor3d(0,0,0);
        }
 
+       EnableTextures(false);
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
        // use glDrawElements to draw each vertexarray
        for (vt=0;vt<vertexarrays.size();vt++)
        {
@@ -191,9 +153,10 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays
                        continue;
                
                glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
-               glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1());
-               glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
                glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
+               glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1());
+               if(glIsEnabled(GL_COLOR_ARRAY))
+                       glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
 
                //if(m_Lock)
                //      local->Begin(vertexarrays[vt]->size());
@@ -203,47 +166,30 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays
 
                //if(m_Lock)
                //      local->End();
-
-
        }
-}
 
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
 
 void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays,
                                                        const vecIndexArrays & indexarrays,
-                                                       int mode,
-                                                       class RAS_IPolyMaterial* polymat,
-                                                       class RAS_IRenderTools* rendertools,
+                                                       DrawMode mode,
                                                        bool useObjectColor,
                                                        const MT_Vector4& rgbacolor,
                                                        class KX_ListSlot** slot)
 {
        static const GLsizei vtxstride = sizeof(RAS_TexVert);
+
        GLenum drawmode;
-       switch (mode)
-       {
-       case 0:
-               {
+       if(mode == KX_MODE_TRIANGLES)
                drawmode = GL_TRIANGLES;
-               break;
-               }
-       case 2:
-               {
+       else if(mode == KX_MODE_QUADS)
                drawmode = GL_QUADS;
-               break;
-               }
-       case 1: //lines
-               {
-               }
-       default:
-               {
+       else
                drawmode = GL_LINES;
-               break;
-               }
-       }
+
        const RAS_TexVert* vertexarray;
        unsigned int numindices, vt;
-       const unsigned int enabled = polymat->GetEnabled();
 
        if (drawmode != GL_LINES)
        {
@@ -251,7 +197,8 @@ void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexa
                {
                        glDisableClientState(GL_COLOR_ARRAY);
                        glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
-               } else
+               }
+               else
                {
                        glColor4d(0,0,0,1.0);
                        glEnableClientState(GL_COLOR_ARRAY);
@@ -271,13 +218,12 @@ void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexa
 
                if (!numindices)
                        continue;
-               
-               glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
-               TexCoordPtr(vertexarray, enabled);
 
-               //glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1());
-               glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
+               glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
                glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
+               TexCoordPtr(vertexarray);
+               if(glIsEnabled(GL_COLOR_ARRAY))
+                       glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
 
                //if(m_Lock)
                //      local->Begin(vertexarrays[vt]->size());
@@ -290,62 +236,161 @@ void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexa
        }
 }
 
-void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv, int enabled)
+void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
 {
-#if defined(GL_ARB_multitexture) && defined(WITH_GLEXT)
-       if (!getenv("WITHOUT_GLEXT")) {
-               if(bgl::RAS_EXT_support._ARB_multitexture)
-               {
-                       for(int unit=0; unit<enabled; unit++)
-                       {
-                               bgl::blClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
+       /* note: this function must closely match EnableTextures to enable/disable
+        * the right arrays, otherwise coordinate and attribute pointers from other
+        * materials can still be used and cause crashes */
+       int unit;
 
+       if(GLEW_ARB_multitexture)
+       {
+               for(unit=0; unit<m_texco_num; unit++)
+               {
+                       glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
+                       if(tv->getFlag() & TV_2NDUV && (int)tv->getUnit() == unit) {
                                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-                               if( tv->getFlag() & TV_2NDUV && tv->getUnit() == unit ) {
-                                       glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
-                                       continue;
-                               }
-                               switch(m_texco[unit])
-                               {
-                               case RAS_TEXCO_DISABLE:
-                               case RAS_TEXCO_OBJECT:
-                               case RAS_TEXCO_GEN:
-                                       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-                                       break;
-                               case RAS_TEXCO_ORCO:
-                               case RAS_TEXCO_GLOB:
-                                       glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getLocalXYZ());
-                                       break;
-                               case RAS_TEXCO_UV1:
-                                       glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
-                                       break;
-                               case RAS_TEXCO_NORM:
-                                       glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
-                                       break;
-                               case RAS_TEXTANGENT:
-                                       glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
-                                       break;
-                               case RAS_TEXCO_UV2:
-                                       glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2());
-                                       break;
-                               }
+                               glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
+                               continue;
+                       }
+                       switch(m_texco[unit])
+                       {
+                       case RAS_TEXCO_ORCO:
+                       case RAS_TEXCO_GLOB:
+                               glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getLocalXYZ());
+                               break;
+                       case RAS_TEXCO_UV1:
+                               glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
+                               break;
+                       case RAS_TEXCO_NORM:
+                               glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
+                               break;
+                       case RAS_TEXTANGENT:
+                               glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
+                               break;
+                       case RAS_TEXCO_UV2:
+                               glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2());
+                               break;
+                       default:
+                               break;
                        }
                }
 
-#ifdef GL_ARB_vertex_program
-               if(m_useTang && bgl::RAS_EXT_support._ARB_vertex_program)
-                       bgl::blVertexAttrib4fvARB(1/*tangent*/, tv->getTangent());
-#endif
+               glClientActiveTextureARB(GL_TEXTURE0_ARB);
        }
-#endif
-}
 
+       if(GLEW_ARB_vertex_program) {
+               for(unit=0; unit<m_attrib_num; unit++) {
+                       switch(m_attrib[unit]) {
+                       case RAS_TEXCO_ORCO:
+                       case RAS_TEXCO_GLOB:
+                               glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ());
+                               break;
+                       case RAS_TEXCO_UV1:
+                               glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1());
+                               break;
+                       case RAS_TEXCO_NORM:
+                               glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal());
+                               break;
+                       case RAS_TEXTANGENT:
+                               glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent());
+                               break;
+                       case RAS_TEXCO_UV2:
+                               glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2());
+                               break;
+                       case RAS_TEXCO_VCOL:
+                               glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA());
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+}
 
 void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
 {
-       if (enable)
-               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-       else
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       TexCoGen *texco, *attrib;
+       int unit, texco_num, attrib_num;
+
+       /* disable previously enabled texture coordinates and attributes. ideally
+        * this shouldn't be necessary .. */
+       if(enable)
+               EnableTextures(false);
+
+       /* we cache last texcoords and attribs to ensure we disable the ones that
+        * were actually last set */
+       if(enable) {
+               texco = m_texco;
+               texco_num = m_texco_num;
+               attrib = m_attrib;
+               attrib_num = m_attrib_num;
+               
+               memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num);
+               m_last_texco_num = m_texco_num;
+               memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num);
+               m_last_attrib_num = m_attrib_num;
+       }
+       else {
+               texco = m_last_texco;
+               texco_num = m_last_texco_num;
+               attrib = m_last_attrib;
+               attrib_num = m_last_attrib_num;
+       }
+
+       if(GLEW_ARB_multitexture) {
+               for(unit=0; unit<texco_num; unit++) {
+                       glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
+
+                       switch(texco[unit])
+                       {
+                       case RAS_TEXCO_ORCO:
+                       case RAS_TEXCO_GLOB:
+                       case RAS_TEXCO_UV1:
+                       case RAS_TEXCO_NORM:
+                       case RAS_TEXTANGENT:
+                       case RAS_TEXCO_UV2:
+                               if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+                               else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+                               break;
+                       default:
+                               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+                               break;
+                       }
+               }
+
+               glClientActiveTextureARB(GL_TEXTURE0_ARB);
+       }
+       else {
+               if(texco_num) {
+                       if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+                       else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+               }
+       }
+
+       if(GLEW_ARB_vertex_program) {
+               for(unit=0; unit<attrib_num; unit++) {
+                       switch(attrib[unit]) {
+                       case RAS_TEXCO_ORCO:
+                       case RAS_TEXCO_GLOB:
+                       case RAS_TEXCO_UV1:
+                       case RAS_TEXCO_NORM:
+                       case RAS_TEXTANGENT:
+                       case RAS_TEXCO_UV2:
+                       case RAS_TEXCO_VCOL:
+                               if(enable) glEnableVertexAttribArrayARB(unit);
+                               else glDisableVertexAttribArrayARB(unit);
+                               break;
+                       default:
+                               glDisableVertexAttribArrayARB(unit);
+                               break;
+                       }
+               }
+       }
+
+       if(!enable) {
+               m_last_texco_num = 0;
+               m_last_attrib_num = 0;
+       }
 }