Blender V2.61 - r43446

KX_BlenderMaterial.cpp

Go to the documentation of this file.
00001 
00005 // ------------------------------------
00006 // ...
00007 // ------------------------------------
00008 #include "GL/glew.h"
00009 
00010 #include "KX_BlenderMaterial.h"
00011 #include "BL_Material.h"
00012 #include "KX_Scene.h"
00013 #include "KX_Light.h"
00014 #include "KX_GameObject.h"
00015 #include "KX_MeshProxy.h"
00016 
00017 #include "MT_Vector3.h"
00018 #include "MT_Vector4.h"
00019 #include "MT_Matrix4x4.h"
00020 
00021 #include "RAS_BucketManager.h"
00022 #include "RAS_MeshObject.h"
00023 #include "RAS_IRasterizer.h"
00024 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
00025 
00026 #include "GPU_draw.h"
00027 
00028 #include "STR_HashedString.h"
00029 
00030 // ------------------------------------
00031 #include "DNA_object_types.h"
00032 #include "DNA_material_types.h"
00033 #include "DNA_image_types.h"
00034 #include "DNA_meshdata_types.h"
00035 #include "BKE_mesh.h"
00036 // ------------------------------------
00037 #include "BLI_utildefines.h"
00038 
00039 #define spit(x) std::cout << x << std::endl;
00040 
00041 BL_Shader *KX_BlenderMaterial::mLastShader = NULL;
00042 BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL;
00043 
00044 //static PyObject *gTextureDict = 0;
00045 
00046 KX_BlenderMaterial::KX_BlenderMaterial()
00047 :   PyObjectPlus(),
00048     RAS_IPolyMaterial(),
00049     mMaterial(NULL),
00050     mShader(0),
00051     mBlenderShader(0),
00052     mScene(NULL),
00053     mUserDefBlend(0),
00054     mModified(0),
00055     mConstructed(false),
00056     mPass(0)
00057 {
00058 }
00059 
00060 void KX_BlenderMaterial::Initialize(
00061     KX_Scene *scene,
00062     BL_Material *data,
00063     GameSettings *game)
00064 {
00065     RAS_IPolyMaterial::Initialize(
00066         data->texname[0],
00067         data->matname,
00068         data->materialindex,
00069         data->tile,
00070         data->tilexrep[0],
00071         data->tileyrep[0],
00072         data->alphablend,
00073         ((data->ras_mode &ALPHA)!=0),
00074         ((data->ras_mode &ZSORT)!=0),
00075         ((data->ras_mode &USE_LIGHT)!=0),
00076         ((data->ras_mode &TEX)),
00077         game
00078     );
00079     mMaterial = data;
00080     mShader = 0;
00081     mBlenderShader = 0;
00082     mScene = scene;
00083     mUserDefBlend = 0;
00084     mModified = 0;
00085     mConstructed = false;
00086     mPass = 0;
00087     // --------------------------------
00088     // RAS_IPolyMaterial variables...
00089     m_flag |= RAS_BLENDERMAT;
00090     m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0;
00091     m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0;
00092     m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0;
00093     m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0;
00094 
00095     // figure max
00096     int enabled = mMaterial->num_enabled;
00097     int max = BL_Texture::GetMaxUnits();
00098     mMaterial->num_enabled = enabled>=max?max:enabled;
00099 
00100     // test the sum of the various modes for equality
00101     // so we can ether accept or reject this material
00102     // as being equal, this is rather important to
00103     // prevent material bleeding
00104     for(int i=0; i<mMaterial->num_enabled; i++) {
00105         m_multimode += (mMaterial->flag[i] + mMaterial->blend_mode[i]);
00106     }
00107     m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT));
00108 }
00109 
00110 KX_BlenderMaterial::~KX_BlenderMaterial()
00111 {
00112     // cleanup work
00113     if (mConstructed)
00114         // clean only if material was actually used
00115         OnExit();
00116 }
00117 
00118 MTFace* KX_BlenderMaterial::GetMTFace(void) const 
00119 {
00120     // fonts on polys
00121     MT_assert(mMaterial->tface);
00122     return mMaterial->tface;
00123 }
00124 
00125 unsigned int* KX_BlenderMaterial::GetMCol(void) const 
00126 {
00127     // fonts on polys
00128     return mMaterial->rgb;
00129 }
00130 
00131 void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
00132 {
00133     if (mMaterial) {
00134         *rgba++ = (unsigned char) (mMaterial->matcolor[0]*255.0);
00135         *rgba++ = (unsigned char) (mMaterial->matcolor[1]*255.0);
00136         *rgba++ = (unsigned char) (mMaterial->matcolor[2]*255.0);
00137         *rgba++ = (unsigned char) (mMaterial->matcolor[3]*255.0);
00138     } else
00139         RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
00140 }
00141 
00142 Material *KX_BlenderMaterial::GetBlenderMaterial() const
00143 {
00144     return mMaterial->material;
00145 }
00146 
00147 Scene* KX_BlenderMaterial::GetBlenderScene() const
00148 {
00149     return mScene->GetBlenderScene();
00150 }
00151 
00152 void KX_BlenderMaterial::ReleaseMaterial()
00153 {
00154     if (mBlenderShader)
00155         mBlenderShader->ReloadMaterial();
00156 }
00157 
00158 void KX_BlenderMaterial::OnConstruction(int layer)
00159 {
00160     if (mConstructed)
00161         // when material are reused between objects
00162         return;
00163     
00164     if(mMaterial->glslmat)
00165         SetBlenderGLSLShader(layer);
00166 
00167     // for each unique material...
00168     int i;
00169     for(i=0; i<mMaterial->num_enabled; i++) {
00170         if( mMaterial->mapping[i].mapping & USEENV ) {
00171             if(!GLEW_ARB_texture_cube_map) {
00172                 spit("CubeMap textures not supported");
00173                 continue;
00174             }
00175             if(!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) )
00176                 spit("unable to initialize image("<<i<<") in "<< 
00177                          mMaterial->matname<< ", image will not be available");
00178         } 
00179     
00180         else {
00181             if( mMaterial->img[i] ) {
00182                 if( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 ))
00183                     spit("unable to initialize image("<<i<<") in "<< 
00184                         mMaterial->matname<< ", image will not be available");
00185             }
00186         }
00187     }
00188 
00189     mBlendFunc[0] =0;
00190     mBlendFunc[1] =0;
00191     mConstructed = true;
00192 }
00193 
00194 void KX_BlenderMaterial::EndFrame()
00195 {
00196     if(mLastBlenderShader) {
00197         mLastBlenderShader->SetProg(false);
00198         mLastBlenderShader = NULL;
00199     }
00200 
00201     if(mLastShader) {
00202         mLastShader->SetProg(false);
00203         mLastShader = NULL;
00204     }
00205 }
00206 
00207 void KX_BlenderMaterial::OnExit()
00208 {
00209     if( mShader ) {
00210         //note, the shader here is allocated, per unique material
00211         //and this function is called per face
00212         if(mShader == mLastShader) {
00213             mShader->SetProg(false);
00214             mLastShader = NULL;
00215         }
00216 
00217         delete mShader;
00218         mShader = 0;
00219     }
00220 
00221     if( mBlenderShader ) {
00222         if(mBlenderShader == mLastBlenderShader) {
00223             mBlenderShader->SetProg(false);
00224             mLastBlenderShader = NULL;
00225         }
00226 
00227         delete mBlenderShader;
00228         mBlenderShader = 0;
00229     }
00230 
00231     BL_Texture::ActivateFirst();
00232     for(int i=0; i<mMaterial->num_enabled; i++) {
00233         BL_Texture::ActivateUnit(i);
00234         mTextures[i].DeleteTex();
00235         mTextures[i].DisableUnit();
00236     }
00237 
00238     if( mMaterial->tface ) 
00239         GPU_set_tpage(mMaterial->tface, 1, mMaterial->alphablend);
00240 }
00241 
00242 
00243 void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
00244 {
00245     MT_assert(GLEW_ARB_shader_objects && mShader);
00246 
00247     int i;
00248     if( !enable || !mShader->Ok() ) {
00249         // frame cleanup.
00250         if(mShader == mLastShader) {
00251             mShader->SetProg(false);
00252             mLastShader = NULL;
00253         }
00254 
00255         ras->SetAlphaBlend(TF_SOLID);
00256         BL_Texture::DisableAllTextures();
00257         return;
00258     }
00259 
00260     BL_Texture::DisableAllTextures();
00261     mShader->SetProg(true);
00262     mLastShader = mShader;
00263     
00264     BL_Texture::ActivateFirst();
00265 
00266     mShader->ApplyShader();
00267 
00268     // for each enabled unit
00269     for(i=0; i<mMaterial->num_enabled; i++) {
00270         if(!mTextures[i].Ok()) continue;
00271         mTextures[i].ActivateTexture();
00272         mTextures[0].SetMapping(mMaterial->mapping[i].mapping);
00273     }
00274 
00275     if(!mUserDefBlend) {
00276         ras->SetAlphaBlend(mMaterial->alphablend);
00277     }
00278     else {
00279         ras->SetAlphaBlend(TF_SOLID);
00280         ras->SetAlphaBlend(-1); // indicates custom mode
00281 
00282         // tested to be valid enums
00283         glEnable(GL_BLEND);
00284         glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
00285     }
00286 }
00287 
00288 void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras)
00289 {
00290     if( !enable || !mBlenderShader->Ok() ) {
00291         ras->SetAlphaBlend(TF_SOLID);
00292 
00293         // frame cleanup.
00294         if(mLastBlenderShader) {
00295             mLastBlenderShader->SetProg(false);
00296             mLastBlenderShader= NULL;
00297         }
00298         else
00299             BL_Texture::DisableAllTextures();
00300 
00301         return;
00302     }
00303 
00304     if(!mBlenderShader->Equals(mLastBlenderShader)) {
00305         ras->SetAlphaBlend(mMaterial->alphablend);
00306 
00307         if(mLastBlenderShader)
00308             mLastBlenderShader->SetProg(false);
00309         else
00310             BL_Texture::DisableAllTextures();
00311 
00312         mBlenderShader->SetProg(true, ras->GetTime());
00313         mLastBlenderShader= mBlenderShader;
00314     }
00315 }
00316 
00317 void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
00318 {
00319     BL_Texture::DisableAllTextures();
00320 
00321     if( !enable ) {
00322         ras->SetAlphaBlend(TF_SOLID);
00323         return;
00324     }
00325 
00326     BL_Texture::ActivateFirst();
00327 
00328     if( mMaterial->IdMode == DEFAULT_BLENDER ) {
00329         ras->SetAlphaBlend(mMaterial->alphablend);
00330         return;
00331     }
00332 
00333     if( mMaterial->IdMode == TEXFACE ) {
00334         // no material connected to the object
00335         if( mTextures[0].Ok() ) {
00336             mTextures[0].ActivateTexture();
00337             mTextures[0].setTexEnv(0, true);
00338             mTextures[0].SetMapping(mMaterial->mapping[0].mapping);
00339             ras->SetAlphaBlend(mMaterial->alphablend);
00340         }
00341         return;
00342     }
00343 
00344     int mode = 0,i=0;
00345     for(i=0; (i<mMaterial->num_enabled && i<MAXTEX); i++) {
00346         if( !mTextures[i].Ok() ) continue;
00347 
00348         mTextures[i].ActivateTexture();
00349         mTextures[i].setTexEnv(mMaterial);
00350         mode = mMaterial->mapping[i].mapping;
00351 
00352         if(mode &USEOBJ)
00353             setObjectMatrixData(i, ras);
00354         else
00355             mTextures[i].SetMapping(mode);
00356         
00357         if(!(mode &USEOBJ))
00358             setTexMatrixData( i );
00359     }
00360 
00361     if(!mUserDefBlend) {
00362         ras->SetAlphaBlend(mMaterial->alphablend);
00363     }
00364     else {
00365         ras->SetAlphaBlend(TF_SOLID);
00366         ras->SetAlphaBlend(-1); // indicates custom mode
00367 
00368         glEnable(GL_BLEND);
00369         glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
00370     }
00371 }
00372 
00373 void
00374 KX_BlenderMaterial::ActivatShaders(
00375     RAS_IRasterizer* rasty, 
00376     TCachingInfo& cachingInfo)const
00377 {
00378     KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
00379 
00380     // reset... 
00381     if(tmp->mMaterial->IsShared()) 
00382         cachingInfo =0;
00383 
00384     if(mLastBlenderShader) {
00385         mLastBlenderShader->SetProg(false);
00386         mLastBlenderShader= NULL;
00387     }
00388 
00389     if (GetCachingInfo() != cachingInfo) {
00390 
00391         if (!cachingInfo)
00392             tmp->setShaderData(false, rasty);
00393         
00394         cachingInfo = GetCachingInfo();
00395     
00396         if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
00397             tmp->setShaderData(true, rasty);
00398         else
00399             tmp->setShaderData(false, rasty);
00400 
00401         if (mMaterial->ras_mode &TWOSIDED)
00402             rasty->SetCullFace(false);
00403         else
00404             rasty->SetCullFace(true);
00405 
00406         if ((mMaterial->ras_mode &WIRE) ||
00407             (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
00408         {       
00409             if (mMaterial->ras_mode &WIRE) 
00410                 rasty->SetCullFace(false);
00411             rasty->SetLines(true);
00412         }
00413         else
00414             rasty->SetLines(false);
00415         ActivatGLMaterials(rasty);
00416         ActivateTexGen(rasty);
00417     }
00418 
00419     //ActivatGLMaterials(rasty);
00420     //ActivateTexGen(rasty);
00421 }
00422 
00423 void
00424 KX_BlenderMaterial::ActivateBlenderShaders(
00425     RAS_IRasterizer* rasty, 
00426     TCachingInfo& cachingInfo)const
00427 {
00428     KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
00429 
00430     if(mLastShader) {
00431         mLastShader->SetProg(false);
00432         mLastShader= NULL;
00433     }
00434 
00435     if (GetCachingInfo() != cachingInfo) {
00436         if (!cachingInfo)
00437             tmp->setBlenderShaderData(false, rasty);
00438         
00439         cachingInfo = GetCachingInfo();
00440     
00441         if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
00442             tmp->setBlenderShaderData(true, rasty);
00443         else
00444             tmp->setBlenderShaderData(false, rasty);
00445 
00446         if (mMaterial->ras_mode &TWOSIDED)
00447             rasty->SetCullFace(false);
00448         else
00449             rasty->SetCullFace(true);
00450 
00451         if ((mMaterial->ras_mode &WIRE) ||
00452             (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
00453         {       
00454             if (mMaterial->ras_mode &WIRE) 
00455                 rasty->SetCullFace(false);
00456             rasty->SetLines(true);
00457         }
00458         else
00459             rasty->SetLines(false);
00460 
00461         ActivatGLMaterials(rasty);
00462         mBlenderShader->SetAttribs(rasty, mMaterial);
00463     }
00464 }
00465 
00466 void
00467 KX_BlenderMaterial::ActivateMat( 
00468     RAS_IRasterizer* rasty,  
00469     TCachingInfo& cachingInfo
00470     )const
00471 {
00472     KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
00473 
00474     if(mLastShader) {
00475         mLastShader->SetProg(false);
00476         mLastShader= NULL;
00477     }
00478 
00479     if(mLastBlenderShader) {
00480         mLastBlenderShader->SetProg(false);
00481         mLastBlenderShader= NULL;
00482     }
00483 
00484     if (GetCachingInfo() != cachingInfo) {
00485         if (!cachingInfo) 
00486             tmp->setTexData( false,rasty );
00487         
00488         cachingInfo = GetCachingInfo();
00489 
00490         if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
00491             tmp->setTexData( true,rasty  );
00492         else
00493             tmp->setTexData( false,rasty);
00494 
00495         if (mMaterial->ras_mode &TWOSIDED)
00496             rasty->SetCullFace(false);
00497         else
00498             rasty->SetCullFace(true);
00499 
00500         if ((mMaterial->ras_mode &WIRE) ||
00501             (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
00502         {       
00503             if (mMaterial->ras_mode &WIRE) 
00504                 rasty->SetCullFace(false);
00505             rasty->SetLines(true);
00506         }
00507         else
00508             rasty->SetLines(false);
00509         ActivatGLMaterials(rasty);
00510         ActivateTexGen(rasty);
00511     }
00512 
00513     //ActivatGLMaterials(rasty);
00514     //ActivateTexGen(rasty);
00515 }
00516 
00517 bool 
00518 KX_BlenderMaterial::Activate( 
00519     RAS_IRasterizer* rasty,  
00520     TCachingInfo& cachingInfo
00521     )const
00522 {
00523     if(GLEW_ARB_shader_objects && (mShader && mShader->Ok())) {
00524         if((mPass++) < mShader->getNumPass() ) {
00525             ActivatShaders(rasty, cachingInfo);
00526             return true;
00527         }
00528         else {
00529             if(mShader == mLastShader) {
00530                 mShader->SetProg(false);
00531                 mLastShader = NULL;
00532             }
00533             mPass = 0;
00534             return false;
00535         }
00536     }
00537     else if( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) {
00538         if(mPass++ == 0) {
00539             ActivateBlenderShaders(rasty, cachingInfo);
00540             return true;
00541         }
00542         else {
00543             mPass = 0;
00544             return false;
00545         }
00546     }
00547     else {
00548         if(mPass++ == 0) {
00549             ActivateMat(rasty, cachingInfo);
00550             return true;
00551         }
00552         else {
00553             mPass = 0;
00554             return false;
00555         }
00556     }
00557 }
00558 
00559 bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const
00560 {
00561     if(!RAS_IPolyMaterial::UsesLighting(rasty))
00562         return false;
00563 
00564     if(mShader && mShader->Ok())
00565         return true;
00566     else if(mBlenderShader && mBlenderShader->Ok())
00567         return false;
00568     else
00569         return true;
00570 }
00571 
00572 void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const
00573 {
00574     if(mShader && GLEW_ARB_shader_objects) {
00575         mShader->Update(ms, rasty);
00576     }
00577     else if(mBlenderShader && GLEW_ARB_shader_objects) {
00578         int alphablend;
00579 
00580         mBlenderShader->Update(ms, rasty);
00581 
00582         /* we do blend modes here, because they can change per object
00583          * with the same material due to obcolor/obalpha */
00584         alphablend = mBlenderShader->GetAlphaBlend();
00585         if(ELEM3(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID)
00586             alphablend = mMaterial->alphablend;
00587 
00588         rasty->SetAlphaBlend(alphablend);
00589     }
00590 }
00591 
00592 void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const
00593 {
00594     if(mShader || !mBlenderShader) {
00595         rasty->SetSpecularity(
00596             mMaterial->speccolor[0]*mMaterial->spec_f,
00597             mMaterial->speccolor[1]*mMaterial->spec_f,
00598             mMaterial->speccolor[2]*mMaterial->spec_f,
00599             mMaterial->spec_f
00600         );
00601 
00602         rasty->SetShinyness( mMaterial->hard );
00603 
00604         rasty->SetDiffuse(
00605             mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, 
00606             mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
00607             mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
00608             1.0f);
00609 
00610         rasty->SetEmissive( 
00611             mMaterial->matcolor[0]*mMaterial->emit,
00612             mMaterial->matcolor[1]*mMaterial->emit,
00613             mMaterial->matcolor[2]*mMaterial->emit,
00614             1.0 );
00615 
00616         rasty->SetAmbient(mMaterial->amb);
00617     }
00618 
00619     if (mMaterial->material)
00620         rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
00621 }
00622 
00623 
00624 void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
00625 {
00626     if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
00627         ras->SetAttribNum(0);
00628         if(mShader && GLEW_ARB_shader_objects) {
00629             if(mShader->GetAttribute() == BL_Shader::SHD_TANGENT) {
00630                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, 0);
00631                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, 1);
00632                 ras->SetAttribNum(2);
00633             }
00634         }
00635 
00636         ras->SetTexCoordNum(mMaterial->num_enabled);
00637 
00638         for(int i=0; i<mMaterial->num_enabled; i++) {
00639             int mode = mMaterial->mapping[i].mapping;
00640 
00641             if (mode &USECUSTOMUV)
00642             {
00643                 if (!mMaterial->mapping[i].uvCoName.IsEmpty())
00644                     ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i);
00645                 continue;
00646             }
00647 
00648             if( mode &(USEREFL|USEOBJ))
00649                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i);
00650             else if(mode &USEORCO)
00651                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_ORCO, i);
00652             else if(mode &USENORM)
00653                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i);
00654             else if(mode &USEUV)
00655                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV1, i);
00656             else if(mode &USETANG)
00657                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i);
00658             else 
00659                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
00660         }
00661     }
00662 }
00663 
00664 void KX_BlenderMaterial::setTexMatrixData(int i)
00665 {
00666     glMatrixMode(GL_TEXTURE);
00667     glLoadIdentity();
00668 
00669     if( GLEW_ARB_texture_cube_map && 
00670         mTextures[i].GetTextureType() == GL_TEXTURE_CUBE_MAP_ARB && 
00671         mMaterial->mapping[i].mapping & USEREFL) {
00672         glScalef( 
00673             mMaterial->mapping[i].scale[0], 
00674             -mMaterial->mapping[i].scale[1], 
00675             -mMaterial->mapping[i].scale[2]
00676         );
00677     }
00678     else
00679     {
00680         glScalef( 
00681             mMaterial->mapping[i].scale[0], 
00682             mMaterial->mapping[i].scale[1], 
00683             mMaterial->mapping[i].scale[2]
00684         );
00685     }
00686     glTranslatef(
00687         mMaterial->mapping[i].offsets[0],
00688         mMaterial->mapping[i].offsets[1], 
00689         mMaterial->mapping[i].offsets[2]
00690     );
00691 
00692     glMatrixMode(GL_MODELVIEW);
00693 
00694 }
00695 
00696 static void GetProjPlane(BL_Material *mat, int index,int num, float*param)
00697 {
00698     param[0]=param[1]=param[2]=param[3]=0.f;
00699     if( mat->mapping[index].projplane[num] == PROJX )
00700         param[0] = 1.f;
00701     else if( mat->mapping[index].projplane[num] == PROJY )
00702         param[1] = 1.f;
00703     else if( mat->mapping[index].projplane[num] == PROJZ)
00704         param[2] = 1.f;
00705 }
00706 
00707 void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras)
00708 {
00709     KX_GameObject *obj = 
00710         (KX_GameObject*)
00711         mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
00712 
00713     if(!obj) return;
00714 
00715     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
00716     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
00717     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
00718 
00719     GLenum plane = GL_EYE_PLANE;
00720 
00721     // figure plane gen
00722     float proj[4]= {0.f,0.f,0.f,0.f};
00723     GetProjPlane(mMaterial, i, 0, proj);
00724     glTexGenfv(GL_S, plane, proj);
00725     
00726     GetProjPlane(mMaterial, i, 1, proj);
00727     glTexGenfv(GL_T, plane, proj);
00728 
00729     GetProjPlane(mMaterial, i, 2, proj);
00730     glTexGenfv(GL_R, plane, proj);
00731 
00732     glEnable(GL_TEXTURE_GEN_S);
00733     glEnable(GL_TEXTURE_GEN_T);
00734     glEnable(GL_TEXTURE_GEN_R);
00735 
00736     const MT_Matrix4x4& mvmat = ras->GetViewMatrix();
00737 
00738     glMatrixMode(GL_TEXTURE);
00739     glLoadIdentity();
00740     glScalef( 
00741         mMaterial->mapping[i].scale[0], 
00742         mMaterial->mapping[i].scale[1], 
00743         mMaterial->mapping[i].scale[2]
00744     );
00745 
00746     MT_Point3 pos = obj->NodeGetWorldPosition();
00747     MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f);
00748     MT_Vector4 t = mvmat*matmul;
00749 
00750     glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) );
00751 
00752     glMatrixMode(GL_MODELVIEW);
00753 
00754 }
00755 
00756 // ------------------------------------
00757 void KX_BlenderMaterial::UpdateIPO(
00758     MT_Vector4 rgba,
00759     MT_Vector3 specrgb,
00760     MT_Scalar hard,
00761     MT_Scalar spec,
00762     MT_Scalar ref,
00763     MT_Scalar emit,
00764     MT_Scalar alpha
00765     )
00766 {
00767     // only works one deep now
00768     mMaterial->speccolor[0] = (float)(specrgb)[0];
00769     mMaterial->speccolor[1] = (float)(specrgb)[1];
00770     mMaterial->speccolor[2] = (float)(specrgb)[2];
00771     mMaterial->matcolor[0]  = (float)(rgba[0]);
00772     mMaterial->matcolor[1]  = (float)(rgba[1]);
00773     mMaterial->matcolor[2]  = (float)(rgba[2]);
00774     mMaterial->alpha        = (float)(alpha);
00775     mMaterial->hard         = (float)(hard);
00776     mMaterial->emit         = (float)(emit);
00777     mMaterial->spec_f       = (float)(spec);
00778     mMaterial->ref          = (float)(ref);
00779 }
00780 
00781 void KX_BlenderMaterial::SetBlenderGLSLShader(int layer)
00782 {
00783     if(!mBlenderShader)
00784         mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer);
00785 
00786     if(!mBlenderShader->Ok()) {
00787         delete mBlenderShader;
00788         mBlenderShader = 0;
00789     }
00790 }
00791 
00792 #ifdef WITH_PYTHON
00793 
00794 PyMethodDef KX_BlenderMaterial::Methods[] = 
00795 {
00796     KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ),
00797     KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ),
00798     KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ),
00799     {NULL,NULL} //Sentinel
00800 };
00801 
00802 PyAttributeDef KX_BlenderMaterial::Attributes[] = {
00803     KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader),
00804     KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex),
00805     KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending),
00806     { NULL }    //Sentinel
00807 };
00808 
00809 PyTypeObject KX_BlenderMaterial::Type = {
00810     PyVarObject_HEAD_INIT(NULL, 0)
00811     "KX_BlenderMaterial",
00812     sizeof(PyObjectPlus_Proxy),
00813     0,
00814     py_base_dealloc,
00815     0,
00816     0,
00817     0,
00818     0,
00819     py_base_repr,
00820     0,0,0,0,0,0,0,0,0,
00821     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00822     0,0,0,0,0,0,0,
00823     Methods,
00824     0,
00825     0,
00826     &PyObjectPlus::Type,
00827     0,0,0,0,0,0,
00828     py_base_new
00829 };
00830 
00831 PyObject* KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00832 {
00833     KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
00834     return self->PygetShader(NULL, NULL);
00835 }
00836 
00837 PyObject* KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00838 {
00839     KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
00840     return PyLong_FromSsize_t(self->GetMaterialIndex());
00841 }
00842 
00843 PyObject* KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00844 {
00845     KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
00846     unsigned int* bfunc = self->getBlendFunc();
00847     return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]);
00848 }
00849 
00850 int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00851 {
00852     KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
00853     PyObject* obj = self->PysetBlending(value, NULL);
00854     if(obj)
00855     {
00856         Py_DECREF(obj);
00857         return 0;
00858     }
00859     return -1;
00860 }
00861 
00862 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
00863 {
00864     if( !GLEW_ARB_fragment_shader) {
00865         if(!mModified)
00866             spit("Fragment shaders not supported");
00867     
00868         mModified = true;
00869         Py_RETURN_NONE;
00870     }
00871 
00872     if( !GLEW_ARB_vertex_shader) {
00873         if(!mModified)
00874             spit("Vertex shaders not supported");
00875 
00876         mModified = true;
00877         Py_RETURN_NONE;
00878     }
00879 
00880     if(!GLEW_ARB_shader_objects)  {
00881         if(!mModified)
00882             spit("GLSL not supported");
00883         mModified = true;
00884         Py_RETURN_NONE;
00885     }
00886     else {
00887         // returns Py_None on error
00888         // the calling script will need to check
00889 
00890         if(!mShader && !mModified) {
00891             mShader = new BL_Shader();
00892             mModified = true;
00893         }
00894 
00895         if(mShader && !mShader->GetError()) {
00896             m_flag &= ~RAS_BLENDERGLSL;
00897             mMaterial->SetSharedMaterial(true);
00898             mScene->GetBucketManager()->ReleaseDisplayLists(this);
00899             return mShader->GetProxy();
00900         }else
00901         {
00902             // decref all references to the object
00903             // then delete it!
00904             // We will then go back to fixed functionality
00905             // for this material
00906             if(mShader) {
00907                 delete mShader; /* will handle python de-referencing */
00908                 mShader=0;
00909             }
00910         }
00911         Py_RETURN_NONE;
00912     }
00913     PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMaterial, GLSL Error");
00914     return NULL;
00915 }
00916 
00917 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
00918 {
00919     return PyLong_FromSsize_t( GetMaterialIndex() );
00920 }
00921 
00922 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
00923 {
00924     // TODO: enable python switching
00925     return NULL;
00926 }
00927 
00928 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
00929 {
00930     // TODO: enable python switching
00931     return NULL;
00932 }
00933 
00934 static unsigned int GL_array[11] = {
00935     GL_ZERO,
00936     GL_ONE,
00937     GL_SRC_COLOR,
00938     GL_ONE_MINUS_SRC_COLOR,
00939     GL_DST_COLOR,
00940     GL_ONE_MINUS_DST_COLOR,
00941     GL_SRC_ALPHA,
00942     GL_ONE_MINUS_SRC_ALPHA,
00943     GL_DST_ALPHA,
00944     GL_ONE_MINUS_DST_ALPHA,
00945     GL_SRC_ALPHA_SATURATE
00946 };
00947 
00948 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( bge.logic.src, bge.logic.dest)")
00949 {
00950     unsigned int b[2];
00951     if(PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1]))
00952     {
00953         bool value_found[2] = {false, false};
00954         for(int i=0; i<11; i++)
00955         {
00956             if(b[0] == GL_array[i]) {
00957                 value_found[0] = true;
00958                 mBlendFunc[0] = b[0];
00959             }
00960             if(b[1] == GL_array[i]) {
00961                 value_found[1] = true;
00962                 mBlendFunc[1] = b[1];
00963             }
00964             if(value_found[0] && value_found[1]) break;
00965         }
00966         if(!value_found[0] || !value_found[1]) {
00967             PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum.");
00968             return NULL;
00969         }
00970         mUserDefBlend = true;
00971         Py_RETURN_NONE;
00972     }
00973     return NULL;
00974 }
00975 
00976 #endif // WITH_PYTHON