Blender V2.61 - r43446

RAS_VAOpenGLRasterizer.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 
00032 #include "RAS_VAOpenGLRasterizer.h"
00033 #include <stdlib.h>
00034 
00035 #include "GL/glew.h"
00036 #include "GPU_extensions.h"
00037 
00038 #include "STR_String.h"
00039 #include "RAS_TexVert.h"
00040 #include "MT_CmMatrix4x4.h"
00041 #include "RAS_IRenderTools.h" // rendering text
00042     
00043 RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock)
00044 :   RAS_OpenGLRasterizer(canvas),
00045     m_Lock(lock && GLEW_EXT_compiled_vertex_array),
00046     m_last_texco_num(0),
00047     m_last_attrib_num(0)
00048 {
00049 }
00050 
00051 RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
00052 {
00053 }
00054 
00055 bool RAS_VAOpenGLRasterizer::Init(void)
00056 {
00057     
00058     bool result = RAS_OpenGLRasterizer::Init();
00059     
00060     if (result)
00061     {
00062         glEnableClientState(GL_VERTEX_ARRAY);
00063         glEnableClientState(GL_NORMAL_ARRAY);
00064         glDisableClientState(GL_COLOR_ARRAY);
00065         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00066 
00067         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00068     }
00069 
00070     return result;
00071 }
00072 
00073 void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
00074 {
00075     m_drawingmode = drawingmode;
00076 
00077     switch (m_drawingmode)
00078     {
00079         case KX_BOUNDINGBOX:
00080         case KX_WIREFRAME:
00081             //glDisableClientState(GL_COLOR_ARRAY);
00082             //glDisable(GL_CULL_FACE);
00083             break;
00084         case KX_SOLID:
00085             //glDisableClientState(GL_COLOR_ARRAY);
00086             break;
00087         case KX_TEXTURED:
00088         case KX_SHADED:
00089         case KX_SHADOW:
00090             //glEnableClientState(GL_COLOR_ARRAY);
00091         default:
00092             break;
00093     }
00094 }
00095 
00096 void RAS_VAOpenGLRasterizer::Exit()
00097 {
00098     glDisableClientState(GL_VERTEX_ARRAY);
00099     glDisableClientState(GL_NORMAL_ARRAY);
00100     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00101     glDisableClientState(GL_COLOR_ARRAY);
00102 
00103     RAS_OpenGLRasterizer::Exit();
00104 }
00105 
00106 void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
00107 {
00108     static const GLsizei stride = sizeof(RAS_TexVert);
00109     bool wireframe = m_drawingmode <= KX_WIREFRAME;
00110     RAS_MeshSlot::iterator it;
00111     GLenum drawmode;
00112 
00113     if (ms.m_pDerivedMesh) {
00114         // cannot be handled here, pass to RAS_OpenGLRasterizer
00115         RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false);
00116         return;
00117     }
00118 
00119     if(!wireframe)
00120         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00121 
00122     // use glDrawElements to draw each vertexarray
00123     for(ms.begin(it); !ms.end(it); ms.next(it)) {
00124         if(it.totindex == 0)
00125             continue;
00126 
00127         // drawing mode
00128         if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
00129             drawmode = GL_TRIANGLES;
00130         else if(it.array->m_type == RAS_DisplayArray::QUAD)
00131             drawmode = GL_QUADS;
00132         else
00133             drawmode = GL_LINES;
00134 
00135         // colors
00136         if (drawmode != GL_LINES && !wireframe) {
00137             if (ms.m_bObjectColor) {
00138                 const MT_Vector4& rgba = ms.m_RGBAcolor;
00139 
00140                 glDisableClientState(GL_COLOR_ARRAY);
00141                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00142             }
00143             else {
00144                 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00145                 glEnableClientState(GL_COLOR_ARRAY);
00146             }
00147         }
00148         else
00149             glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00150 
00151         glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
00152         glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
00153         if(!wireframe) {
00154             glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1());
00155             if(glIsEnabled(GL_COLOR_ARRAY))
00156                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
00157         }
00158 
00159         // here the actual drawing takes places
00160         glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
00161     }
00162 
00163     if(!wireframe) {
00164         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00165         glDisableClientState(GL_COLOR_ARRAY);
00166     }
00167 }
00168 
00169 void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
00170 {
00171     static const GLsizei stride = sizeof(RAS_TexVert);
00172     bool wireframe = m_drawingmode <= KX_WIREFRAME;
00173     RAS_MeshSlot::iterator it;
00174     GLenum drawmode;
00175 
00176     if (ms.m_pDerivedMesh) {
00177         // cannot be handled here, pass to RAS_OpenGLRasterizer
00178         RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true);
00179         return;
00180     }
00181 
00182     if(!wireframe)
00183         EnableTextures(true);
00184 
00185     // use glDrawElements to draw each vertexarray
00186     for(ms.begin(it); !ms.end(it); ms.next(it)) {
00187         if(it.totindex == 0)
00188             continue;
00189 
00190         // drawing mode
00191         if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
00192             drawmode = GL_TRIANGLES;
00193         else if(it.array->m_type == RAS_DisplayArray::QUAD)
00194             drawmode = GL_QUADS;
00195         else
00196             drawmode = GL_LINES;
00197 
00198         // colors
00199         if (drawmode != GL_LINES && !wireframe) {
00200             if (ms.m_bObjectColor) {
00201                 const MT_Vector4& rgba = ms.m_RGBAcolor;
00202 
00203                 glDisableClientState(GL_COLOR_ARRAY);
00204                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00205             }
00206             else {
00207                 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00208                 glEnableClientState(GL_COLOR_ARRAY);
00209             }
00210         }
00211         else
00212             glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00213 
00214         glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
00215         glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
00216         if(!wireframe) {
00217             TexCoordPtr(it.vertex);
00218             if(glIsEnabled(GL_COLOR_ARRAY))
00219                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
00220         }
00221 
00222         // here the actual drawing takes places
00223         glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
00224     }
00225 
00226     if(!wireframe) {
00227         glDisableClientState(GL_COLOR_ARRAY);
00228         EnableTextures(false);
00229     }
00230 }
00231 
00232 void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
00233 {
00234     /* note: this function must closely match EnableTextures to enable/disable
00235      * the right arrays, otherwise coordinate and attribute pointers from other
00236      * materials can still be used and cause crashes */
00237     int unit;
00238 
00239     if(GLEW_ARB_multitexture)
00240     {
00241         for(unit=0; unit<m_texco_num; unit++)
00242         {
00243             glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
00244             if(tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) {
00245                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00246                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
00247                 continue;
00248             }
00249             switch(m_texco[unit])
00250             {
00251             case RAS_TEXCO_ORCO:
00252             case RAS_TEXCO_GLOB:
00253                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ());
00254                 break;
00255             case RAS_TEXCO_UV1:
00256                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
00257                 break;
00258             case RAS_TEXCO_NORM:
00259                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
00260                 break;
00261             case RAS_TEXTANGENT:
00262                 glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
00263                 break;
00264             case RAS_TEXCO_UV2:
00265                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2());
00266                 break;
00267             default:
00268                 break;
00269             }
00270         }
00271 
00272         glClientActiveTextureARB(GL_TEXTURE0_ARB);
00273     }
00274 
00275     if(GLEW_ARB_vertex_program) {
00276         for(unit=0; unit<m_attrib_num; unit++) {
00277             switch(m_attrib[unit]) {
00278             case RAS_TEXCO_ORCO:
00279             case RAS_TEXCO_GLOB:
00280                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ());
00281                 break;
00282             case RAS_TEXCO_UV1:
00283                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1());
00284                 break;
00285             case RAS_TEXCO_NORM:
00286                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal());
00287                 break;
00288             case RAS_TEXTANGENT:
00289                 glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent());
00290                 break;
00291             case RAS_TEXCO_UV2:
00292                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2());
00293                 break;
00294             case RAS_TEXCO_VCOL:
00295                 glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA());
00296                 break;
00297             default:
00298                 break;
00299             }
00300         }
00301     }
00302 }
00303 
00304 void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
00305 {
00306     TexCoGen *texco, *attrib;
00307     int unit, texco_num, attrib_num;
00308 
00309     /* we cache last texcoords and attribs to ensure we disable the ones that
00310      * were actually last set */
00311     if(enable) {
00312         texco = m_texco;
00313         texco_num = m_texco_num;
00314         attrib = m_attrib;
00315         attrib_num = m_attrib_num;
00316         
00317         memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num);
00318         m_last_texco_num = m_texco_num;
00319         memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num);
00320         m_last_attrib_num = m_attrib_num;
00321     }
00322     else {
00323         texco = m_last_texco;
00324         texco_num = m_last_texco_num;
00325         attrib = m_last_attrib;
00326         attrib_num = m_last_attrib_num;
00327     }
00328 
00329     if(GLEW_ARB_multitexture) {
00330         for(unit=0; unit<texco_num; unit++) {
00331             glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
00332 
00333             switch(texco[unit])
00334             {
00335             case RAS_TEXCO_ORCO:
00336             case RAS_TEXCO_GLOB:
00337             case RAS_TEXCO_UV1:
00338             case RAS_TEXCO_NORM:
00339             case RAS_TEXTANGENT:
00340             case RAS_TEXCO_UV2:
00341                 if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00342                 else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00343                 break;
00344             default:
00345                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00346                 break;
00347             }
00348         }
00349 
00350         glClientActiveTextureARB(GL_TEXTURE0_ARB);
00351     }
00352     else {
00353         if(texco_num) {
00354             if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00355             else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00356         }
00357     }
00358 
00359     if(GLEW_ARB_vertex_program) {
00360         for(unit=0; unit<attrib_num; unit++) {
00361             switch(attrib[unit]) {
00362             case RAS_TEXCO_ORCO:
00363             case RAS_TEXCO_GLOB:
00364             case RAS_TEXCO_UV1:
00365             case RAS_TEXCO_NORM:
00366             case RAS_TEXTANGENT:
00367             case RAS_TEXCO_UV2:
00368             case RAS_TEXCO_VCOL:
00369                 if(enable) glEnableVertexAttribArrayARB(unit);
00370                 else glDisableVertexAttribArrayARB(unit);
00371                 break;
00372             default:
00373                 glDisableVertexAttribArrayARB(unit);
00374                 break;
00375             }
00376         }
00377     }
00378 
00379     if(!enable) {
00380         m_last_texco_num = 0;
00381         m_last_attrib_num = 0;
00382     }
00383 }
00384