Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_VAOpenGLRasterizer.cpp
index 77beed5ead12aabdc3b2711541bd254738d7a528..c78a97ad7beec843be144685b04ff35abaa7ddae 100644 (file)
@@ -1,14 +1,11 @@
 /**
  * $Id$
 /**
  * $Id$
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  *
  * Contributor(s): none yet.
  *
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include "RAS_VAOpenGLRasterizer.h"
  */
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include "RAS_VAOpenGLRasterizer.h"
+#include <stdlib.h>
 
 
-#ifdef WIN32
-#include <windows.h>
-#endif // WIN32
-#ifdef __APPLE__
-#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 "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)
-:RAS_OpenGLRasterizer(canvas)
+RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock)
+:      RAS_OpenGLRasterizer(canvas),
+       m_Lock(lock && GLEW_EXT_compiled_vertex_array),
+       m_last_texco_num(0),
+       m_last_attrib_num(0)
 {
 }
 
 {
 }
 
-
-
 RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
 {
 }
 
 RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
 {
 }
 
-
-
 bool RAS_VAOpenGLRasterizer::Init(void)
 {
        
 bool RAS_VAOpenGLRasterizer::Init(void)
 {
        
@@ -74,9 +59,9 @@ bool RAS_VAOpenGLRasterizer::Init(void)
        if (result)
        {
                glEnableClientState(GL_VERTEX_ARRAY);
        if (result)
        {
                glEnableClientState(GL_VERTEX_ARRAY);
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
                glEnableClientState(GL_NORMAL_ARRAY);
                glDisableClientState(GL_COLOR_ARRAY);
                glEnableClientState(GL_NORMAL_ARRAY);
                glDisableClientState(GL_COLOR_ARRAY);
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        }
 
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        }
@@ -84,86 +69,59 @@ bool RAS_VAOpenGLRasterizer::Init(void)
        return result;
 }
 
        return result;
 }
 
-
-
 void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
 {
        m_drawingmode = drawingmode;
 
 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;
                        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);
                        glEnableClientState(GL_COLOR_ARRAY);
-               }
-       case KX_SOLID:
-               {
+               default:
                        break;
                        break;
-               }
-       default:
-               {
-               }
        }
 }
 
        }
 }
 
-
-
 void RAS_VAOpenGLRasterizer::Exit()
 {
 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_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
-       glDisableClientState(GL_NORMAL_ARRAY);
+       EnableTextures(false);
 
        RAS_OpenGLRasterizer::Exit();
 }
 
 
        RAS_OpenGLRasterizer::Exit();
 }
 
-
-
 void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays,
                                                        const vecIndexArrays & indexarrays,
 void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays,
                                                        const vecIndexArrays & indexarrays,
-                                                       int mode,
-                                                       class RAS_IPolyMaterial* polymat,
-                                                       class RAS_IRenderTools* rendertools,
+                                                       DrawMode mode,
                                                        bool useObjectColor,
                                                        bool useObjectColor,
-                                                       const MT_Vector4& rgbacolor)
+                                                       const MT_Vector4& rgbacolor,
+                                                       class KX_ListSlot** slot)
 {
        static const GLsizei vtxstride = sizeof(RAS_TexVert);
        GLenum drawmode;
 {
        static const GLsizei vtxstride = sizeof(RAS_TexVert);
        GLenum drawmode;
-       switch (mode)
-       {
-       case 0:
-               {
+       if(mode == KX_MODE_TRIANGLES)
                drawmode = GL_TRIANGLES;
                drawmode = GL_TRIANGLES;
-               break;
-               }
-       case 2:
-               {
+       else if(mode == KX_MODE_QUADS)
                drawmode = GL_QUADS;
                drawmode = GL_QUADS;
-               break;
-               }
-       case 1: //lines
-               {
-               }
-       default:
-               {
+       else
                drawmode = GL_LINES;
                drawmode = GL_LINES;
-               break;
-               }
-       }
+
        const RAS_TexVert* vertexarray;
        unsigned int numindices, vt;
        const RAS_TexVert* vertexarray;
        unsigned int numindices, vt;
+
        if (drawmode != GL_LINES)
        {
                if (useObjectColor)
        if (drawmode != GL_LINES)
        {
                if (useObjectColor)
@@ -180,34 +138,259 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays
        {
                glColor3d(0,0,0);
        }
        {
                glColor3d(0,0,0);
        }
+
+       EnableTextures(false);
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
        // use glDrawElements to draw each vertexarray
        for (vt=0;vt<vertexarrays.size();vt++)
        {
                vertexarray = &((*vertexarrays[vt]) [0]);
                const KX_IndexArray & indexarray = (*indexarrays[vt]);
                numindices = indexarray.size();
        // use glDrawElements to draw each vertexarray
        for (vt=0;vt<vertexarrays.size();vt++)
        {
                vertexarray = &((*vertexarrays[vt]) [0]);
                const KX_IndexArray & indexarray = (*indexarrays[vt]);
                numindices = indexarray.size();
-               // int numverts = vertexarrays[vt]->size();
 
                if (!numindices)
                        continue;
                
                glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
 
                if (!numindices)
                        continue;
                
                glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
+               glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
                glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1());
                glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1());
-               glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
+               if(glIsEnabled(GL_COLOR_ARRAY))
+                       glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
+
+               //if(m_Lock)
+               //      local->Begin(vertexarrays[vt]->size());
+
+               // here the actual drawing takes places
+               glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0]));
+
+               //if(m_Lock)
+               //      local->End();
+       }
+
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays,
+                                                       const vecIndexArrays & indexarrays,
+                                                       DrawMode mode,
+                                                       bool useObjectColor,
+                                                       const MT_Vector4& rgbacolor,
+                                                       class KX_ListSlot** slot)
+{
+       static const GLsizei vtxstride = sizeof(RAS_TexVert);
+
+       GLenum drawmode;
+       if(mode == KX_MODE_TRIANGLES)
+               drawmode = GL_TRIANGLES;
+       else if(mode == KX_MODE_QUADS)
+               drawmode = GL_QUADS;
+       else
+               drawmode = GL_LINES;
+
+       const RAS_TexVert* vertexarray;
+       unsigned int numindices, vt;
+
+       if (drawmode != GL_LINES)
+       {
+               if (useObjectColor)
+               {
+                       glDisableClientState(GL_COLOR_ARRAY);
+                       glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+               }
+               else
+               {
+                       glColor4d(0,0,0,1.0);
+                       glEnableClientState(GL_COLOR_ARRAY);
+               }
+       }
+       else
+       {
+               glColor3d(0,0,0);
+       }
+
+       // use glDrawElements to draw each vertexarray
+       for (vt=0;vt<vertexarrays.size();vt++)
+       {
+               vertexarray = &((*vertexarrays[vt]) [0]);
+               const KX_IndexArray & indexarray = (*indexarrays[vt]);
+               numindices = indexarray.size();
+
+               if (!numindices)
+                       continue;
+
+               glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
                glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
                glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
-               //glLockArraysEXT(0,numverts);
+               TexCoordPtr(vertexarray);
+               if(glIsEnabled(GL_COLOR_ARRAY))
+                       glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
+
+               //if(m_Lock)
+               //      local->Begin(vertexarrays[vt]->size());
+
                // here the actual drawing takes places
                glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0]));
                // here the actual drawing takes places
                glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0]));
-               //glUnlockArraysEXT();
+               
+               //if(m_Lock)
+               //      local->End();
        }
 }
 
        }
 }
 
+void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
+{
+       /* 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);
+                               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;
+                       }
+               }
+
+               glClientActiveTextureARB(GL_TEXTURE0_ARB);
+       }
+
+       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)
 {
 
 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;
+       }
 }
 
 }