Committing patch #25675 "Make "Cast Buffer Shadows" option work in viewport and BGE...
[blender.git] / source / gameengine / Ketsji / KX_BlenderMaterial.cpp
1 /** \file gameengine/Ketsji/KX_BlenderMaterial.cpp
2  *  \ingroup ketsji
3  */
4
5 // ------------------------------------
6 // ...
7 // ------------------------------------
8 #include "GL/glew.h"
9
10 #include "KX_BlenderMaterial.h"
11 #include "BL_Material.h"
12 #include "KX_Scene.h"
13 #include "KX_Light.h"
14 #include "KX_GameObject.h"
15 #include "KX_MeshProxy.h"
16
17 #include "MT_Vector3.h"
18 #include "MT_Vector4.h"
19 #include "MT_Matrix4x4.h"
20
21 #include "RAS_BucketManager.h"
22 #include "RAS_MeshObject.h"
23 #include "RAS_IRasterizer.h"
24 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
25
26 #include "GPU_draw.h"
27
28 #include "STR_HashedString.h"
29
30 // ------------------------------------
31 #include "DNA_object_types.h"
32 #include "DNA_material_types.h"
33 #include "DNA_image_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "BKE_mesh.h"
36 // ------------------------------------
37 #define spit(x) std::cout << x << std::endl;
38
39 BL_Shader *KX_BlenderMaterial::mLastShader = NULL;
40 BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL;
41
42 //static PyObject *gTextureDict = 0;
43
44 KX_BlenderMaterial::KX_BlenderMaterial()
45 :       PyObjectPlus(),
46         RAS_IPolyMaterial(),
47         mMaterial(NULL),
48         mShader(0),
49         mBlenderShader(0),
50         mScene(NULL),
51         mUserDefBlend(0),
52         mModified(0),
53         mConstructed(false),
54         mPass(0)
55 {
56 }
57
58 void KX_BlenderMaterial::Initialize(
59     KX_Scene *scene,
60         BL_Material *data)
61 {
62         RAS_IPolyMaterial::Initialize(
63                 data->texname[0],
64                 data->matname,
65                 data->materialindex,
66                 data->tile,
67                 data->tilexrep[0],
68                 data->tileyrep[0],
69                 data->mode,
70                 data->transp,
71                 ((data->ras_mode &ALPHA)!=0),
72                 ((data->ras_mode &ZSORT)!=0)
73         );
74         mMaterial = data;
75         mShader = 0;
76         mBlenderShader = 0;
77         mScene = scene;
78         mUserDefBlend = 0;
79         mModified = 0;
80         mConstructed = false;
81         mPass = 0;
82         // --------------------------------
83         // RAS_IPolyMaterial variables... 
84         m_flag |= RAS_BLENDERMAT;
85         m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0;
86         m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0;
87         m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0;
88         m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0;
89
90         // figure max
91         int enabled = mMaterial->num_enabled;
92         int max = BL_Texture::GetMaxUnits();
93         mMaterial->num_enabled = enabled>=max?max:enabled;
94
95         // test the sum of the various modes for equality
96         // so we can ether accept or reject this material 
97         // as being equal, this is rather important to 
98         // prevent material bleeding
99         for(int i=0; i<mMaterial->num_enabled; i++) {
100                 m_multimode     +=
101                         ( mMaterial->flag[i]    +
102                           mMaterial->blend_mode[i]
103                          );
104         }
105         m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT));
106 }
107
108 KX_BlenderMaterial::~KX_BlenderMaterial()
109 {
110         // cleanup work
111         if (mConstructed)
112                 // clean only if material was actually used
113                 OnExit();
114 }
115
116 MTFace* KX_BlenderMaterial::GetMTFace(void) const 
117 {
118         // fonts on polys
119         MT_assert(mMaterial->tface);
120         return mMaterial->tface;
121 }
122
123 unsigned int* KX_BlenderMaterial::GetMCol(void) const 
124 {
125         // fonts on polys
126         return mMaterial->rgb;
127 }
128
129 void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
130 {
131         if (mMaterial) {
132                 *rgba++ = (unsigned char) (mMaterial->matcolor[0]*255.0);
133                 *rgba++ = (unsigned char) (mMaterial->matcolor[1]*255.0);
134                 *rgba++ = (unsigned char) (mMaterial->matcolor[2]*255.0);
135                 *rgba++ = (unsigned char) (mMaterial->matcolor[3]*255.0);
136         } else
137                 RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
138 }
139
140 Material *KX_BlenderMaterial::GetBlenderMaterial() const
141 {
142         return mMaterial->material;
143 }
144
145 Scene* KX_BlenderMaterial::GetBlenderScene() const
146 {
147         return mScene->GetBlenderScene();
148 }
149
150 void KX_BlenderMaterial::ReleaseMaterial()
151 {
152         if (mBlenderShader)
153                 mBlenderShader->ReloadMaterial();
154 }
155
156 void KX_BlenderMaterial::OnConstruction(int layer)
157 {
158         if (mConstructed)
159                 // when material are reused between objects
160                 return;
161         
162         if(mMaterial->glslmat)
163                 SetBlenderGLSLShader(layer);
164
165         // for each unique material...
166         int i;
167         for(i=0; i<mMaterial->num_enabled; i++) {
168                 if( mMaterial->mapping[i].mapping & USEENV ) {
169                         if(!GLEW_ARB_texture_cube_map) {
170                                 spit("CubeMap textures not supported");
171                                 continue;
172                         }
173                         if(!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) )
174                                 spit("unable to initialize image("<<i<<") in "<< 
175                                                  mMaterial->matname<< ", image will not be available");
176                 } 
177         
178                 else {
179                         if( mMaterial->img[i] ) {
180                                 if( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 ))
181                                         spit("unable to initialize image("<<i<<") in "<< 
182                                                 mMaterial->matname<< ", image will not be available");
183                         }
184                 }
185         }
186
187         mBlendFunc[0] =0;
188         mBlendFunc[1] =0;
189         mConstructed = true;
190 }
191
192 void KX_BlenderMaterial::EndFrame()
193 {
194         if(mLastBlenderShader) {
195                 mLastBlenderShader->SetProg(false);
196                 mLastBlenderShader = NULL;
197         }
198
199         if(mLastShader) {
200                 mLastShader->SetProg(false);
201                 mLastShader = NULL;
202         }
203 }
204
205 void KX_BlenderMaterial::OnExit()
206 {
207         if( mShader ) {
208                 //note, the shader here is allocated, per unique material
209                 //and this function is called per face
210                 if(mShader == mLastShader) {
211                         mShader->SetProg(false);
212                         mLastShader = NULL;
213                 }
214
215                 delete mShader;
216                 mShader = 0;
217         }
218
219         if( mBlenderShader ) {
220                 if(mBlenderShader == mLastBlenderShader) {
221                         mBlenderShader->SetProg(false);
222                         mLastBlenderShader = NULL;
223                 }
224
225                 delete mBlenderShader;
226                 mBlenderShader = 0;
227         }
228
229         BL_Texture::ActivateFirst();
230         for(int i=0; i<mMaterial->num_enabled; i++) {
231                 BL_Texture::ActivateUnit(i);
232                 mTextures[i].DeleteTex();
233                 mTextures[i].DisableUnit();
234         }
235
236         if( mMaterial->tface ) 
237                 GPU_set_tpage(mMaterial->tface, 1);
238 }
239
240
241 void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
242 {
243         MT_assert(GLEW_ARB_shader_objects && mShader);
244
245         int i;
246         if( !enable || !mShader->Ok() ) {
247                 // frame cleanup.
248                 if(mShader == mLastShader) {
249                         mShader->SetProg(false);
250                         mLastShader = NULL;
251                 }
252
253                 ras->SetBlendingMode(TF_SOLID);
254                 BL_Texture::DisableAllTextures();
255                 return;
256         }
257
258         BL_Texture::DisableAllTextures();
259         mShader->SetProg(true);
260         mLastShader = mShader;
261         
262         BL_Texture::ActivateFirst();
263
264         mShader->ApplyShader();
265
266         // for each enabled unit
267         for(i=0; i<mMaterial->num_enabled; i++) {
268                 if(!mTextures[i].Ok()) continue;
269                 mTextures[i].ActivateTexture();
270                 mTextures[0].SetMapping(mMaterial->mapping[i].mapping);
271         }
272
273         if(!mUserDefBlend) {
274                 ras->SetBlendingMode(mMaterial->transp);
275         }
276         else {
277                 ras->SetBlendingMode(TF_SOLID);
278                 ras->SetBlendingMode(-1); // indicates custom mode
279
280                 // tested to be valid enums
281                 glEnable(GL_BLEND);
282                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
283         }
284 }
285
286 void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras)
287 {
288         if( !enable || !mBlenderShader->Ok() ) {
289                 ras->SetBlendingMode(TF_SOLID);
290
291                 // frame cleanup.
292                 if(mLastBlenderShader) {
293                         mLastBlenderShader->SetProg(false);
294                         mLastBlenderShader= NULL;
295                 }
296                 else
297                         BL_Texture::DisableAllTextures();
298
299                 return;
300         }
301
302         if(!mBlenderShader->Equals(mLastBlenderShader)) {
303                 ras->SetBlendingMode(mMaterial->transp);
304
305                 if(mLastBlenderShader)
306                         mLastBlenderShader->SetProg(false);
307                 else
308                         BL_Texture::DisableAllTextures();
309
310                 mBlenderShader->SetProg(true, ras->GetTime());
311                 mLastBlenderShader= mBlenderShader;
312         }
313 }
314
315 void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
316 {
317         BL_Texture::DisableAllTextures();
318
319         if( !enable ) {
320                 ras->SetBlendingMode(TF_SOLID);
321                 return;
322         }
323
324         BL_Texture::ActivateFirst();
325
326         if( mMaterial->IdMode == DEFAULT_BLENDER ) {
327                 ras->SetBlendingMode(mMaterial->transp);
328                 return;
329         }
330
331         if( mMaterial->IdMode == TEXFACE ) {
332                 // no material connected to the object
333                 if( mTextures[0].Ok() ) {
334                         mTextures[0].ActivateTexture();
335                         mTextures[0].setTexEnv(0, true);
336                         mTextures[0].SetMapping(mMaterial->mapping[0].mapping);
337                         ras->SetBlendingMode(mMaterial->transp);
338                 }
339                 return;
340         }
341
342         int mode = 0,i=0;
343         for(i=0; (i<mMaterial->num_enabled && i<MAXTEX); i++) {
344                 if( !mTextures[i].Ok() ) continue;
345
346                 mTextures[i].ActivateTexture();
347                 mTextures[i].setTexEnv(mMaterial);
348                 mode = mMaterial->mapping[i].mapping;
349
350                 if(mode &USEOBJ)
351                         setObjectMatrixData(i, ras);
352                 else
353                         mTextures[i].SetMapping(mode);
354                 
355                 if(!(mode &USEOBJ))
356                         setTexMatrixData( i );
357         }
358
359         if(!mUserDefBlend) {
360                 ras->SetBlendingMode(mMaterial->transp);
361         }
362         else {
363                 ras->SetBlendingMode(TF_SOLID);
364                 ras->SetBlendingMode(-1); // indicates custom mode
365
366                 glEnable(GL_BLEND);
367                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
368         }
369 }
370
371 void
372 KX_BlenderMaterial::ActivatShaders(
373         RAS_IRasterizer* rasty, 
374         TCachingInfo& cachingInfo)const
375 {
376         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
377
378         // reset... 
379         if(tmp->mMaterial->IsShared()) 
380                 cachingInfo =0;
381
382         if(mLastBlenderShader) {
383                 mLastBlenderShader->SetProg(false);
384                 mLastBlenderShader= NULL;
385         }
386
387         if (GetCachingInfo() != cachingInfo) {
388
389                 if (!cachingInfo)
390                         tmp->setShaderData(false, rasty);
391                 
392                 cachingInfo = GetCachingInfo();
393         
394                 if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
395                         tmp->setShaderData(true, rasty);
396                 else
397                         tmp->setShaderData(false, rasty);
398
399                 if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
400                         rasty->SetCullFace(false);
401                 else
402                         rasty->SetCullFace(true);
403
404                 if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) ||
405                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
406                 {               
407                         if((mMaterial->ras_mode &WIRE)!=0) 
408                                 rasty->SetCullFace(false);
409                         rasty->SetLines(true);
410                 }
411                 else
412                         rasty->SetLines(false);
413                 ActivatGLMaterials(rasty);
414                 ActivateTexGen(rasty);
415         }
416
417         //ActivatGLMaterials(rasty);
418         //ActivateTexGen(rasty);
419 }
420
421 void
422 KX_BlenderMaterial::ActivateBlenderShaders(
423         RAS_IRasterizer* rasty, 
424         TCachingInfo& cachingInfo)const
425 {
426         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
427
428         if(mLastShader) {
429                 mLastShader->SetProg(false);
430                 mLastShader= NULL;
431         }
432
433         if (GetCachingInfo() != cachingInfo) {
434                 if (!cachingInfo)
435                         tmp->setBlenderShaderData(false, rasty);
436                 
437                 cachingInfo = GetCachingInfo();
438         
439                 if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
440                         tmp->setBlenderShaderData(true, rasty);
441                 else
442                         tmp->setBlenderShaderData(false, rasty);
443
444                 if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
445                         rasty->SetCullFace(false);
446                 else
447                         rasty->SetCullFace(true);
448
449                 if (((mMaterial->ras_mode & WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) ||
450                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
451                 {               
452                         if((mMaterial->ras_mode &WIRE)!=0) 
453                                 rasty->SetCullFace(false);
454                         rasty->SetLines(true);
455                 }
456                 else
457                         rasty->SetLines(false);
458
459                 ActivatGLMaterials(rasty);
460                 mBlenderShader->SetAttribs(rasty, mMaterial);
461         }
462 }
463
464 void
465 KX_BlenderMaterial::ActivateMat( 
466         RAS_IRasterizer* rasty,  
467         TCachingInfo& cachingInfo
468         )const
469 {
470         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
471
472         if(mLastShader) {
473                 mLastShader->SetProg(false);
474                 mLastShader= NULL;
475         }
476
477         if(mLastBlenderShader) {
478                 mLastBlenderShader->SetProg(false);
479                 mLastBlenderShader= NULL;
480         }
481
482         if (GetCachingInfo() != cachingInfo) {
483                 if (!cachingInfo) 
484                         tmp->setTexData( false,rasty );
485                 
486                 cachingInfo = GetCachingInfo();
487
488                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
489                         tmp->setTexData( true,rasty  );
490                 else
491                         tmp->setTexData( false,rasty);
492
493                 if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
494                         rasty->SetCullFace(false);
495                 else
496                         rasty->SetCullFace(true);
497
498                 if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) ||
499                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
500                 {               
501                         if((mMaterial->ras_mode &WIRE)!=0) 
502                                 rasty->SetCullFace(false);
503                         rasty->SetLines(true);
504                 }
505                 else
506                         rasty->SetLines(false);
507                 ActivatGLMaterials(rasty);
508                 ActivateTexGen(rasty);
509         }
510
511         //ActivatGLMaterials(rasty);
512         //ActivateTexGen(rasty);
513 }
514
515 bool 
516 KX_BlenderMaterial::Activate( 
517         RAS_IRasterizer* rasty,  
518         TCachingInfo& cachingInfo
519         )const
520 {
521         if(GLEW_ARB_shader_objects && (mShader && mShader->Ok())) {
522                 if((mPass++) < mShader->getNumPass() ) {
523                         ActivatShaders(rasty, cachingInfo);
524                         return true;
525                 }
526                 else {
527                         if(mShader == mLastShader) {
528                                 mShader->SetProg(false);
529                                 mLastShader = NULL;
530                         }
531                         mPass = 0;
532                         return false;
533                 }
534         }
535         else if( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) {
536                 if(mPass++ == 0) {
537                         ActivateBlenderShaders(rasty, cachingInfo);
538                         return true;
539                 }
540                 else {
541                         mPass = 0;
542                         return false;
543                 }
544         }
545         else {
546                 if(mPass++ == 0) {
547                         ActivateMat(rasty, cachingInfo);
548                         return true;
549                 }
550                 else {
551                         mPass = 0;
552                         return false;
553                 }
554         }
555 }
556
557 bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const
558 {
559         if(!RAS_IPolyMaterial::UsesLighting(rasty))
560                 return false;
561
562         if(mShader && mShader->Ok())
563                 return true;
564         else if(mBlenderShader && mBlenderShader->Ok())
565                 return false;
566         else
567                 return true;
568 }
569
570 void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const
571 {
572         if(mShader && GLEW_ARB_shader_objects) {
573                 mShader->Update(ms, rasty);
574         }
575         else if(mBlenderShader && GLEW_ARB_shader_objects) {
576                 int blendmode;
577
578                 mBlenderShader->Update(ms, rasty);
579
580                 /* we do blend modes here, because they can change per object
581                  * with the same material due to obcolor/obalpha */
582                 blendmode = mBlenderShader->GetBlendMode();
583                 if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID)
584                         blendmode = mMaterial->transp;
585
586                 rasty->SetBlendingMode(blendmode);
587         }
588 }
589
590 void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const
591 {
592         if(mShader || !mBlenderShader) {
593                 rasty->SetSpecularity(
594                         mMaterial->speccolor[0]*mMaterial->spec_f,
595                         mMaterial->speccolor[1]*mMaterial->spec_f,
596                         mMaterial->speccolor[2]*mMaterial->spec_f,
597                         mMaterial->spec_f
598                 );
599
600                 rasty->SetShinyness( mMaterial->hard );
601
602                 rasty->SetDiffuse(
603                         mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, 
604                         mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
605                         mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
606                         1.0f);
607
608                 rasty->SetEmissive(     
609                         mMaterial->matcolor[0]*mMaterial->emit,
610                         mMaterial->matcolor[1]*mMaterial->emit,
611                         mMaterial->matcolor[2]*mMaterial->emit,
612                         1.0 );
613
614                 rasty->SetAmbient(mMaterial->amb);
615         }
616
617         if (mMaterial->material)
618                 rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
619 }
620
621
622 void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
623 {
624         if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
625                 ras->SetAttribNum(0);
626                 if(mShader && GLEW_ARB_shader_objects) {
627                         if(mShader->GetAttribute() == BL_Shader::SHD_TANGENT) {
628                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, 0);
629                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, 1);
630                                 ras->SetAttribNum(2);
631                         }
632                 }
633
634                 ras->SetTexCoordNum(mMaterial->num_enabled);
635
636                 for(int i=0; i<mMaterial->num_enabled; i++) {
637                         int mode = mMaterial->mapping[i].mapping;
638
639                         if (mode &USECUSTOMUV)
640                         {
641                                 if (!mMaterial->mapping[i].uvCoName.IsEmpty())
642                                         ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i);
643                                 continue;
644                         }
645
646                         if( mode &(USEREFL|USEOBJ))
647                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i);
648                         else if(mode &USEORCO)
649                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_ORCO, i);
650                         else if(mode &USENORM)
651                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i);
652                         else if(mode &USEUV)
653                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV1, i);
654                         else if(mode &USETANG)
655                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i);
656                         else 
657                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
658                 }
659         }
660 }
661
662 void KX_BlenderMaterial::setTexMatrixData(int i)
663 {
664         glMatrixMode(GL_TEXTURE);
665         glLoadIdentity();
666
667         if( GLEW_ARB_texture_cube_map && 
668                 mTextures[i].GetTextureType() == GL_TEXTURE_CUBE_MAP_ARB && 
669                 mMaterial->mapping[i].mapping & USEREFL) {
670                 glScalef( 
671                         mMaterial->mapping[i].scale[0], 
672                         -mMaterial->mapping[i].scale[1], 
673                         -mMaterial->mapping[i].scale[2]
674                 );
675         }
676         else
677         {
678                 glScalef( 
679                         mMaterial->mapping[i].scale[0], 
680                         mMaterial->mapping[i].scale[1], 
681                         mMaterial->mapping[i].scale[2]
682                 );
683         }
684         glTranslatef(
685                 mMaterial->mapping[i].offsets[0],
686                 mMaterial->mapping[i].offsets[1], 
687                 mMaterial->mapping[i].offsets[2]
688         );
689
690         glMatrixMode(GL_MODELVIEW);
691
692 }
693
694 static void GetProjPlane(BL_Material *mat, int index,int num, float*param)
695 {
696         param[0]=param[1]=param[2]=param[3]=0.f;
697         if( mat->mapping[index].projplane[num] == PROJX )
698                 param[0] = 1.f;
699         else if( mat->mapping[index].projplane[num] == PROJY )
700                 param[1] = 1.f;
701         else if( mat->mapping[index].projplane[num] == PROJZ)
702                 param[2] = 1.f;
703 }
704
705 void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras)
706 {
707         KX_GameObject *obj = 
708                 (KX_GameObject*)
709                 mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
710
711         if(!obj) return;
712
713         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
714         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
715         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
716
717         GLenum plane = GL_EYE_PLANE;
718
719         // figure plane gen
720         float proj[4]= {0.f,0.f,0.f,0.f};
721         GetProjPlane(mMaterial, i, 0, proj);
722         glTexGenfv(GL_S, plane, proj);
723         
724         GetProjPlane(mMaterial, i, 1, proj);
725         glTexGenfv(GL_T, plane, proj);
726
727         GetProjPlane(mMaterial, i, 2, proj);
728         glTexGenfv(GL_R, plane, proj);
729
730         glEnable(GL_TEXTURE_GEN_S);
731         glEnable(GL_TEXTURE_GEN_T);
732         glEnable(GL_TEXTURE_GEN_R);
733
734         const MT_Matrix4x4& mvmat = ras->GetViewMatrix();
735
736         glMatrixMode(GL_TEXTURE);
737         glLoadIdentity();
738         glScalef( 
739                 mMaterial->mapping[i].scale[0], 
740                 mMaterial->mapping[i].scale[1], 
741                 mMaterial->mapping[i].scale[2]
742         );
743
744         MT_Point3 pos = obj->NodeGetWorldPosition();
745         MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f);
746         MT_Vector4 t = mvmat*matmul;
747
748         glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) );
749
750         glMatrixMode(GL_MODELVIEW);
751
752 }
753
754 // ------------------------------------
755 void KX_BlenderMaterial::UpdateIPO(
756         MT_Vector4 rgba,
757         MT_Vector3 specrgb,
758         MT_Scalar hard,
759         MT_Scalar spec,
760         MT_Scalar ref,
761         MT_Scalar emit,
762         MT_Scalar alpha
763         )
764 {
765         // only works one deep now
766         mMaterial->speccolor[0] = (float)(specrgb)[0];
767         mMaterial->speccolor[1] = (float)(specrgb)[1];
768         mMaterial->speccolor[2] = (float)(specrgb)[2];
769         mMaterial->matcolor[0]  = (float)(rgba[0]);
770         mMaterial->matcolor[1]  = (float)(rgba[1]);
771         mMaterial->matcolor[2]  = (float)(rgba[2]);
772         mMaterial->alpha                = (float)(alpha);
773         mMaterial->hard                 = (float)(hard);
774         mMaterial->emit                 = (float)(emit);
775         mMaterial->spec_f               = (float)(spec);
776         mMaterial->ref                  = (float)(ref);
777 }
778
779 void KX_BlenderMaterial::SetBlenderGLSLShader(int layer)
780 {
781         if(!mBlenderShader)
782                 mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer);
783
784         if(!mBlenderShader->Ok()) {
785                 delete mBlenderShader;
786                 mBlenderShader = 0;
787         }
788 }
789
790 #ifdef WITH_PYTHON
791
792 PyMethodDef KX_BlenderMaterial::Methods[] = 
793 {
794         KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ),
795         KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ),
796         KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ),
797         {NULL,NULL} //Sentinel
798 };
799
800 PyAttributeDef KX_BlenderMaterial::Attributes[] = {
801         KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader),
802         KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex),
803         KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending),
804         { NULL }        //Sentinel
805 };
806
807 PyTypeObject KX_BlenderMaterial::Type = {
808         PyVarObject_HEAD_INIT(NULL, 0)
809         "KX_BlenderMaterial",
810         sizeof(PyObjectPlus_Proxy),
811         0,
812         py_base_dealloc,
813         0,
814         0,
815         0,
816         0,
817         py_base_repr,
818         0,0,0,0,0,0,0,0,0,
819         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
820         0,0,0,0,0,0,0,
821         Methods,
822         0,
823         0,
824         &PyObjectPlus::Type,
825         0,0,0,0,0,0,
826         py_base_new
827 };
828
829 PyObject* KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
830 {
831         KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
832         return self->PygetShader(NULL, NULL);
833 }
834
835 PyObject* KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
836 {
837         KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
838         return PyLong_FromSsize_t(self->GetMaterialIndex());
839 }
840
841 PyObject* KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
842 {
843         KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
844         unsigned int* bfunc = self->getBlendFunc();
845         return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]);
846 }
847
848 int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
849 {
850         KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
851         PyObject* obj = self->PysetBlending(value, NULL);
852         if(obj)
853         {
854                 Py_DECREF(obj);
855                 return 0;
856         }
857         return -1;
858 }
859
860 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
861 {
862         if( !GLEW_ARB_fragment_shader) {
863                 if(!mModified)
864                         spit("Fragment shaders not supported");
865         
866                 mModified = true;
867                 Py_RETURN_NONE;
868         }
869
870         if( !GLEW_ARB_vertex_shader) {
871                 if(!mModified)
872                         spit("Vertex shaders not supported");
873
874                 mModified = true;
875                 Py_RETURN_NONE;
876         }
877
878         if(!GLEW_ARB_shader_objects)  {
879                 if(!mModified)
880                         spit("GLSL not supported");
881                 mModified = true;
882                 Py_RETURN_NONE;
883         }
884         else {
885                 // returns Py_None on error
886                 // the calling script will need to check
887
888                 if(!mShader && !mModified) {
889                         mShader = new BL_Shader();
890                         mModified = true;
891                 }
892
893                 if(mShader && !mShader->GetError()) {
894                         m_flag &= ~RAS_BLENDERGLSL;
895                         mMaterial->SetSharedMaterial(true);
896                         mScene->GetBucketManager()->ReleaseDisplayLists(this);
897                         return mShader->GetProxy();
898                 }else
899                 {
900                         // decref all references to the object
901                         // then delete it!
902                         // We will then go back to fixed functionality
903                         // for this material
904                         if(mShader) {
905                                 delete mShader; /* will handle python de-referencing */
906                                 mShader=0;
907                         }
908                 }
909                 Py_RETURN_NONE;
910         }
911         PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMaterial, GLSL Error");
912         return NULL;
913 }
914
915 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
916 {
917         return PyLong_FromSsize_t( GetMaterialIndex() );
918 }
919
920 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
921 {
922         // TODO: enable python switching
923         return NULL;
924 }
925
926 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
927 {
928         // TODO: enable python switching
929         return NULL;
930 }
931
932 static unsigned int GL_array[11] = {
933         GL_ZERO,
934         GL_ONE,
935         GL_SRC_COLOR,
936         GL_ONE_MINUS_SRC_COLOR,
937         GL_DST_COLOR,
938         GL_ONE_MINUS_DST_COLOR,
939         GL_SRC_ALPHA,
940         GL_ONE_MINUS_SRC_ALPHA,
941         GL_DST_ALPHA,
942         GL_ONE_MINUS_DST_ALPHA,
943         GL_SRC_ALPHA_SATURATE
944 };
945
946 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( bge.logic.src, bge.logic.dest)")
947 {
948         unsigned int b[2];
949         if(PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1]))
950         {
951                 bool value_found[2] = {false, false};
952                 for(int i=0; i<11; i++)
953                 {
954                         if(b[0] == GL_array[i]) {
955                                 value_found[0] = true;
956                                 mBlendFunc[0] = b[0];
957                         }
958                         if(b[1] == GL_array[i]) {
959                                 value_found[1] = true;
960                                 mBlendFunc[1] = b[1];
961                         }
962                         if(value_found[0] && value_found[1]) break;
963                 }
964                 if(!value_found[0] || !value_found[1]) {
965                         PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum.");
966                         return NULL;
967                 }
968                 mUserDefBlend = true;
969                 Py_RETURN_NONE;
970         }
971         return NULL;
972 }
973
974 #endif // WITH_PYTHON