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