Blender  V2.59
RAS_VAOpenGLRasterizer.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: RAS_VAOpenGLRasterizer.cpp 35174 2011-02-25 13:38:24Z jesterking $
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): none yet.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00033 #include "RAS_VAOpenGLRasterizer.h"
00034 #include <stdlib.h>
00035 
00036 #include "GL/glew.h"
00037 #include "GPU_extensions.h"
00038 
00039 #include "STR_String.h"
00040 #include "RAS_TexVert.h"
00041 #include "MT_CmMatrix4x4.h"
00042 #include "RAS_IRenderTools.h" // rendering text
00043         
00044 RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock)
00045 :       RAS_OpenGLRasterizer(canvas),
00046         m_Lock(lock && GLEW_EXT_compiled_vertex_array),
00047         m_last_texco_num(0),
00048         m_last_attrib_num(0)
00049 {
00050 }
00051 
00052 RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
00053 {
00054 }
00055 
00056 bool RAS_VAOpenGLRasterizer::Init(void)
00057 {
00058         
00059         bool result = RAS_OpenGLRasterizer::Init();
00060         
00061         if (result)
00062         {
00063                 glEnableClientState(GL_VERTEX_ARRAY);
00064                 glEnableClientState(GL_NORMAL_ARRAY);
00065                 glDisableClientState(GL_COLOR_ARRAY);
00066                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00067 
00068                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00069         }
00070 
00071         return result;
00072 }
00073 
00074 void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
00075 {
00076         m_drawingmode = drawingmode;
00077 
00078         switch (m_drawingmode)
00079         {
00080                 case KX_BOUNDINGBOX:
00081                 case KX_WIREFRAME:
00082                         //glDisableClientState(GL_COLOR_ARRAY);
00083                         //glDisable(GL_CULL_FACE);
00084                         break;
00085                 case KX_SOLID:
00086                         //glDisableClientState(GL_COLOR_ARRAY);
00087                         break;
00088                 case KX_TEXTURED:
00089                 case KX_SHADED:
00090                 case KX_SHADOW:
00091                         //glEnableClientState(GL_COLOR_ARRAY);
00092                 default:
00093                         break;
00094         }
00095 }
00096 
00097 void RAS_VAOpenGLRasterizer::Exit()
00098 {
00099         glDisableClientState(GL_VERTEX_ARRAY);
00100         glDisableClientState(GL_NORMAL_ARRAY);
00101         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00102         glDisableClientState(GL_COLOR_ARRAY);
00103 
00104         RAS_OpenGLRasterizer::Exit();
00105 }
00106 
00107 void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
00108 {
00109         static const GLsizei stride = sizeof(RAS_TexVert);
00110         bool wireframe = m_drawingmode <= KX_WIREFRAME;
00111         RAS_MeshSlot::iterator it;
00112         GLenum drawmode;
00113 
00114         if (ms.m_pDerivedMesh) {
00115                 // cannot be handled here, pass to RAS_OpenGLRasterizer
00116                 RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false);
00117                 return;
00118         }
00119 
00120         if(!wireframe)
00121                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00122 
00123         // use glDrawElements to draw each vertexarray
00124         for(ms.begin(it); !ms.end(it); ms.next(it)) {
00125                 if(it.totindex == 0)
00126                         continue;
00127 
00128                 // drawing mode
00129                 if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
00130                         drawmode = GL_TRIANGLES;
00131                 else if(it.array->m_type == RAS_DisplayArray::QUAD)
00132                         drawmode = GL_QUADS;
00133                 else
00134                         drawmode = GL_LINES;
00135 
00136                 // colors
00137                 if (drawmode != GL_LINES && !wireframe) {
00138                         if (ms.m_bObjectColor) {
00139                                 const MT_Vector4& rgba = ms.m_RGBAcolor;
00140 
00141                                 glDisableClientState(GL_COLOR_ARRAY);
00142                                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00143                         }
00144                         else {
00145                                 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00146                                 glEnableClientState(GL_COLOR_ARRAY);
00147                         }
00148                 }
00149                 else
00150                         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00151 
00152                 glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
00153                 glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
00154                 if(!wireframe) {
00155                         glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1());
00156                         if(glIsEnabled(GL_COLOR_ARRAY))
00157                                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
00158                 }
00159 
00160                 // here the actual drawing takes places
00161                 glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
00162         }
00163 
00164         if(!wireframe) {
00165                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00166                 glDisableClientState(GL_COLOR_ARRAY);
00167         }
00168 }
00169 
00170 void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
00171 {
00172         static const GLsizei stride = sizeof(RAS_TexVert);
00173         bool wireframe = m_drawingmode <= KX_WIREFRAME;
00174         RAS_MeshSlot::iterator it;
00175         GLenum drawmode;
00176 
00177         if (ms.m_pDerivedMesh) {
00178                 // cannot be handled here, pass to RAS_OpenGLRasterizer
00179                 RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true);
00180                 return;
00181         }
00182 
00183         if(!wireframe)
00184                 EnableTextures(true);
00185 
00186         // use glDrawElements to draw each vertexarray
00187         for(ms.begin(it); !ms.end(it); ms.next(it)) {
00188                 if(it.totindex == 0)
00189                         continue;
00190 
00191                 // drawing mode
00192                 if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
00193                         drawmode = GL_TRIANGLES;
00194                 else if(it.array->m_type == RAS_DisplayArray::QUAD)
00195                         drawmode = GL_QUADS;
00196                 else
00197                         drawmode = GL_LINES;
00198 
00199                 // colors
00200                 if (drawmode != GL_LINES && !wireframe) {
00201                         if (ms.m_bObjectColor) {
00202                                 const MT_Vector4& rgba = ms.m_RGBAcolor;
00203 
00204                                 glDisableClientState(GL_COLOR_ARRAY);
00205                                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
00206                         }
00207                         else {
00208                                 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00209                                 glEnableClientState(GL_COLOR_ARRAY);
00210                         }
00211                 }
00212                 else
00213                         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00214 
00215                 glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
00216                 glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
00217                 if(!wireframe) {
00218                         TexCoordPtr(it.vertex);
00219                         if(glIsEnabled(GL_COLOR_ARRAY))
00220                                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
00221                 }
00222 
00223                 // here the actual drawing takes places
00224                 glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
00225         }
00226 
00227         if(!wireframe) {
00228                 glDisableClientState(GL_COLOR_ARRAY);
00229                 EnableTextures(false);
00230         }
00231 }
00232 
00233 void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
00234 {
00235         /* note: this function must closely match EnableTextures to enable/disable
00236          * the right arrays, otherwise coordinate and attribute pointers from other
00237          * materials can still be used and cause crashes */
00238         int unit;
00239 
00240         if(GLEW_ARB_multitexture)
00241         {
00242                 for(unit=0; unit<m_texco_num; unit++)
00243                 {
00244                         glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
00245                         if(tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) {
00246                                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00247                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
00248                                 continue;
00249                         }
00250                         switch(m_texco[unit])
00251                         {
00252                         case RAS_TEXCO_ORCO:
00253                         case RAS_TEXCO_GLOB:
00254                                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ());
00255                                 break;
00256                         case RAS_TEXCO_UV1:
00257                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
00258                                 break;
00259                         case RAS_TEXCO_NORM:
00260                                 glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
00261                                 break;
00262                         case RAS_TEXTANGENT:
00263                                 glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
00264                                 break;
00265                         case RAS_TEXCO_UV2:
00266                                 glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2());
00267                                 break;
00268                         default:
00269                                 break;
00270                         }
00271                 }
00272 
00273                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00274         }
00275 
00276         if(GLEW_ARB_vertex_program) {
00277                 for(unit=0; unit<m_attrib_num; unit++) {
00278                         switch(m_attrib[unit]) {
00279                         case RAS_TEXCO_ORCO:
00280                         case RAS_TEXCO_GLOB:
00281                                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ());
00282                                 break;
00283                         case RAS_TEXCO_UV1:
00284                                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1());
00285                                 break;
00286                         case RAS_TEXCO_NORM:
00287                                 glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal());
00288                                 break;
00289                         case RAS_TEXTANGENT:
00290                                 glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent());
00291                                 break;
00292                         case RAS_TEXCO_UV2:
00293                                 glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2());
00294                                 break;
00295                         case RAS_TEXCO_VCOL:
00296                                 glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA());
00297                                 break;
00298                         default:
00299                                 break;
00300                         }
00301                 }
00302         }
00303 }
00304 
00305 void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
00306 {
00307         TexCoGen *texco, *attrib;
00308         int unit, texco_num, attrib_num;
00309 
00310         /* we cache last texcoords and attribs to ensure we disable the ones that
00311          * were actually last set */
00312         if(enable) {
00313                 texco = m_texco;
00314                 texco_num = m_texco_num;
00315                 attrib = m_attrib;
00316                 attrib_num = m_attrib_num;
00317                 
00318                 memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num);
00319                 m_last_texco_num = m_texco_num;
00320                 memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num);
00321                 m_last_attrib_num = m_attrib_num;
00322         }
00323         else {
00324                 texco = m_last_texco;
00325                 texco_num = m_last_texco_num;
00326                 attrib = m_last_attrib;
00327                 attrib_num = m_last_attrib_num;
00328         }
00329 
00330         if(GLEW_ARB_multitexture) {
00331                 for(unit=0; unit<texco_num; unit++) {
00332                         glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
00333 
00334                         switch(texco[unit])
00335                         {
00336                         case RAS_TEXCO_ORCO:
00337                         case RAS_TEXCO_GLOB:
00338                         case RAS_TEXCO_UV1:
00339                         case RAS_TEXCO_NORM:
00340                         case RAS_TEXTANGENT:
00341                         case RAS_TEXCO_UV2:
00342                                 if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00343                                 else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00344                                 break;
00345                         default:
00346                                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00347                                 break;
00348                         }
00349                 }
00350 
00351                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00352         }
00353         else {
00354                 if(texco_num) {
00355                         if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00356                         else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00357                 }
00358         }
00359 
00360         if(GLEW_ARB_vertex_program) {
00361                 for(unit=0; unit<attrib_num; unit++) {
00362                         switch(attrib[unit]) {
00363                         case RAS_TEXCO_ORCO:
00364                         case RAS_TEXCO_GLOB:
00365                         case RAS_TEXCO_UV1:
00366                         case RAS_TEXCO_NORM:
00367                         case RAS_TEXTANGENT:
00368                         case RAS_TEXCO_UV2:
00369                         case RAS_TEXCO_VCOL:
00370                                 if(enable) glEnableVertexAttribArrayARB(unit);
00371                                 else glDisableVertexAttribArrayARB(unit);
00372                                 break;
00373                         default:
00374                                 glDisableVertexAttribArrayARB(unit);
00375                                 break;
00376                         }
00377                 }
00378         }
00379 
00380         if(!enable) {
00381                 m_last_texco_num = 0;
00382                 m_last_attrib_num = 0;
00383         }
00384 }
00385