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