Changeset View
Changeset View
Standalone View
Standalone View
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
| Context not available. | |||||
| * \ingroup ketsji | * \ingroup ketsji | ||||
| */ | */ | ||||
| #include "glew-mx.h" | |||||
| #include "KX_BlenderMaterial.h" | #include "KX_BlenderMaterial.h" | ||||
| #include "BL_Material.h" | |||||
| #include "KX_Scene.h" | #include "KX_Scene.h" | ||||
| #include "KX_Light.h" | |||||
| #include "KX_GameObject.h" | |||||
| #include "KX_MeshProxy.h" | |||||
| #include "KX_PyMath.h" | #include "KX_PyMath.h" | ||||
| #include "MT_Vector3.h" | #include "BL_Shader.h" | ||||
| #include "MT_Vector4.h" | #include "BL_BlenderShader.h" | ||||
| #include "EXP_ListWrapper.h" | |||||
| #include "MT_Matrix4x4.h" | #include "MT_Matrix4x4.h" | ||||
| #include "RAS_BucketManager.h" | #include "RAS_BucketManager.h" | ||||
| #include "RAS_MeshObject.h" | |||||
| #include "RAS_IRasterizer.h" | #include "RAS_IRasterizer.h" | ||||
| #include "RAS_MeshUser.h" | |||||
| #include "GPU_draw.h" | #include "GPU_draw.h" | ||||
| #include "GPU_material.h" // for GPU_BLEND_SOLID | |||||
| #include "STR_HashedString.h" | #include "DNA_texture_types.h" | ||||
| // ------------------------------------ | |||||
| #include "DNA_object_types.h" | |||||
| #include "DNA_material_types.h" | #include "DNA_material_types.h" | ||||
| #include "DNA_image_types.h" | |||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "BKE_mesh.h" | #include "DNA_scene_types.h" | ||||
| // ------------------------------------ | |||||
| #include "BLI_utildefines.h" | KX_BlenderMaterial::KX_BlenderMaterial( | ||||
| #include "BLI_math.h" | KX_Scene *scene, | ||||
| Material *mat, | |||||
| #define spit(x) std::cout << x << std::endl; | GameSettings *game, | ||||
| MTFace *mtface, | |||||
| BL_Shader *KX_BlenderMaterial::mLastShader = NULL; | int lightlayer) | ||||
| BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; | :RAS_IPolyMaterial(mat->id.name, game), | ||||
| m_material(mat), | |||||
| //static PyObject *gTextureDict = 0; | m_shader(NULL), | ||||
| m_blenderShader(NULL), | |||||
| KX_BlenderMaterial::KX_BlenderMaterial() | m_scene(scene), | ||||
| : PyObjectPlus(), | m_userDefBlend(false), | ||||
| RAS_IPolyMaterial(), | m_constructed(false), | ||||
| mMaterial(NULL), | m_lightLayer(lightlayer) | ||||
| mShader(0), | { | ||||
| mBlenderShader(0), | |||||
| mScene(NULL), | |||||
| mUserDefBlend(0), | |||||
| mModified(0), | |||||
| mConstructed(false), | |||||
| mPass(0) | |||||
| { | |||||
| } | |||||
| void KX_BlenderMaterial::Initialize( | |||||
| KX_Scene *scene, | |||||
| BL_Material *data, | |||||
| GameSettings *game, | |||||
| int lightlayer) | |||||
| { | |||||
| RAS_IPolyMaterial::Initialize( | |||||
| data->texname[0], | |||||
| data->matname, | |||||
| data->materialindex, | |||||
| data->tile, | |||||
| data->tilexrep[0], | |||||
| data->tileyrep[0], | |||||
| data->alphablend, | |||||
| ((data->ras_mode &ALPHA)!=0), | |||||
| ((data->ras_mode &ZSORT)!=0), | |||||
| ((data->ras_mode &USE_LIGHT)!=0), | |||||
| ((data->ras_mode &TEX)), | |||||
| game | |||||
| ); | |||||
| Material *ma = data->material; | |||||
| // Save material data to restore on exit | // Save material data to restore on exit | ||||
| mSavedData.r = ma->r; | m_savedData.r = m_material->r; | ||||
| mSavedData.g = ma->g; | m_savedData.g = m_material->g; | ||||
| mSavedData.b = ma->b; | m_savedData.b = m_material->b; | ||||
| mSavedData.a = ma->alpha; | m_savedData.a = m_material->alpha; | ||||
| mSavedData.specr = ma->specr; | m_savedData.specr = m_material->specr; | ||||
| mSavedData.specg = ma->specg; | m_savedData.specg = m_material->specg; | ||||
| mSavedData.specb = ma->specb; | m_savedData.specb = m_material->specb; | ||||
| mSavedData.spec = ma->spec; | m_savedData.spec = m_material->spec; | ||||
| mSavedData.ref = ma->ref; | m_savedData.ref = m_material->ref; | ||||
| mSavedData.hardness = ma->har; | m_savedData.hardness = m_material->har; | ||||
| mSavedData.emit = ma->emit; | m_savedData.emit = m_material->emit; | ||||
| m_savedData.ambient = m_material->amb; | |||||
| mMaterial = data; | m_savedData.specularalpha = m_material->spectra; | ||||
| mShader = 0; | |||||
| mBlenderShader = 0; | m_alphablend = mat->game.alpha_blend; | ||||
| mScene = scene; | |||||
| mUserDefBlend = 0; | m_mtexPoly = new MTexPoly(); | ||||
| mModified = 0; | memset(m_mtexPoly, 0, sizeof(MTexPoly)); | ||||
| mConstructed = false; | |||||
| mPass = 0; | if (mtface) { | ||||
| mLightLayer = lightlayer; | ME_MTEXFACE_CPY(m_mtexPoly, mtface); | ||||
| // -------------------------------- | } | ||||
| // RAS_IPolyMaterial variables... | |||||
| m_flag |= RAS_BLENDERMAT; | // with ztransp enabled, enforce alpha blending mode | ||||
| m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0; | if ((mat->mode & MA_TRANSP) && (mat->mode & MA_ZTRANSP) && (m_alphablend == GEMAT_SOLID)) { | ||||
| m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0; | m_alphablend = GEMAT_ALPHA; | ||||
| m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0; | |||||
| m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0; | |||||
| m_flag |= ((mMaterial->ras_mode & ONLY_SHADOW)!=0)? RAS_ONLYSHADOW: 0; | |||||
| // test the sum of the various modes for equality | |||||
| // so we can ether accept or reject this material | |||||
| // as being equal, this is rather important to | |||||
| // prevent material bleeding | |||||
| for (int i=0; i<BL_Texture::GetMaxUnits(); i++) { | |||||
| m_multimode += (mMaterial->flag[i] + mMaterial->blend_mode[i]); | |||||
| } | } | ||||
| m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT)); | |||||
| m_rasMode |= (mat->game.flag & GEMAT_BACKCULL) ? 0 : RAS_TWOSIDED; | |||||
| m_rasMode |= (mat->material_type == MA_TYPE_WIRE) ? RAS_WIRE : 0; | |||||
| m_rasMode |= (mat->mode2 & MA_DEPTH_TRANSP) ? RAS_DEPTH_ALPHA : 0; | |||||
| // always zsort alpha + add | |||||
| if (ELEM(m_alphablend, GEMAT_ALPHA, GEMAT_ALPHA_SORT, GEMAT_ADD) && (m_alphablend != GEMAT_CLIP)) { | |||||
| m_rasMode |= RAS_ALPHA; | |||||
| m_rasMode |= (mat && (mat->game.alpha_blend & GEMAT_ALPHA_SORT)) ? RAS_ZSORT : 0; | |||||
| } | |||||
| // RAS_IPolyMaterial variables... | |||||
| m_flag |= ((mat->mode & MA_SHLESS) != 0) ? 0 : RAS_MULTILIGHT; | |||||
| m_flag |= RAS_BLENDERGLSL; | |||||
| m_flag |= ((mat->mode2 & MA_CASTSHADOW) != 0) ? RAS_CASTSHADOW : 0; | |||||
| m_flag |= ((mat->mode & MA_ONLYCAST) != 0) ? RAS_ONLYSHADOW : 0; | |||||
| m_flag |= ((m_material->shade_flag & MA_OBCOLOR) != 0) ? RAS_OBJECTCOLOR : 0; | |||||
| InitTextures(); | |||||
| } | } | ||||
| KX_BlenderMaterial::~KX_BlenderMaterial() | KX_BlenderMaterial::~KX_BlenderMaterial() | ||||
| { | { | ||||
| Material *ma = mMaterial->material; | |||||
| // Restore Blender material data | // Restore Blender material data | ||||
| ma->r = mSavedData.r; | m_material->r = m_savedData.r; | ||||
| ma->g = mSavedData.g; | m_material->g = m_savedData.g; | ||||
| ma->b = mSavedData.b; | m_material->b = m_savedData.b; | ||||
| ma->alpha = mSavedData.a; | m_material->alpha = m_savedData.a; | ||||
| ma->specr = mSavedData.specr; | m_material->specr = m_savedData.specr; | ||||
| ma->specg = mSavedData.specg; | m_material->specg = m_savedData.specg; | ||||
| ma->specb = mSavedData.specb; | m_material->specb = m_savedData.specb; | ||||
| ma->spec = mSavedData.spec; | m_material->spec = m_savedData.spec; | ||||
| ma->ref = mSavedData.ref; | m_material->ref = m_savedData.ref; | ||||
| ma->har = mSavedData.hardness; | m_material->har = m_savedData.hardness; | ||||
| ma->emit = mSavedData.emit; | m_material->emit = m_savedData.emit; | ||||
| m_material->amb = m_savedData.ambient; | |||||
| m_material->spectra = m_savedData.specularalpha; | |||||
| delete m_mtexPoly; | |||||
| // cleanup work | // cleanup work | ||||
| if (mConstructed) | if (m_constructed) { | ||||
| // clean only if material was actually used | // clean only if material was actually used | ||||
| OnExit(); | OnExit(); | ||||
| } | |||||
| } | } | ||||
| MTexPoly *KX_BlenderMaterial::GetMTexPoly() const | MTexPoly *KX_BlenderMaterial::GetMTexPoly() const | ||||
| { | { | ||||
| // fonts on polys | // fonts on polys | ||||
| return &mMaterial->mtexpoly; | return m_mtexPoly; | ||||
| } | } | ||||
| unsigned int* KX_BlenderMaterial::GetMCol() const | void KX_BlenderMaterial::GetRGBAColor(unsigned char *rgba) const | ||||
| { | { | ||||
| // fonts on polys | if (m_material) { | ||||
| return mMaterial->rgb; | *rgba++ = (unsigned char)(m_material->r * 255.0f); | ||||
| *rgba++ = (unsigned char)(m_material->g * 255.0f); | |||||
| *rgba++ = (unsigned char)(m_material->b * 255.0f); | |||||
| *rgba++ = (unsigned char)(m_material->alpha * 255.0f); | |||||
| } | |||||
| else | |||||
| RAS_IPolyMaterial::GetRGBAColor(rgba); | |||||
| } | } | ||||
| void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const | const std::string KX_BlenderMaterial::GetTextureName() const | ||||
| { | { | ||||
| if (mMaterial) { | return (m_textures[0] ? m_textures[0]->GetName() : ""); | ||||
| *rgba++ = (unsigned char)(mMaterial->matcolor[0] * 255.0f); | |||||
| *rgba++ = (unsigned char)(mMaterial->matcolor[1] * 255.0f); | |||||
| *rgba++ = (unsigned char)(mMaterial->matcolor[2] * 255.0f); | |||||
| *rgba++ = (unsigned char)(mMaterial->matcolor[3] * 255.0f); | |||||
| } else | |||||
| RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); | |||||
| } | } | ||||
| Material *KX_BlenderMaterial::GetBlenderMaterial() const | Material *KX_BlenderMaterial::GetBlenderMaterial() const | ||||
| { | { | ||||
| return mMaterial->material; | return m_material; | ||||
| } | } | ||||
| Image *KX_BlenderMaterial::GetBlenderImage() const | Image *KX_BlenderMaterial::GetBlenderImage() const | ||||
| { | { | ||||
| return mMaterial->mtexpoly.tpage; | return (m_mtexPoly ? m_mtexPoly->tpage : NULL); | ||||
| } | } | ||||
| Scene* KX_BlenderMaterial::GetBlenderScene() const | Scene *KX_BlenderMaterial::GetBlenderScene() const | ||||
| { | { | ||||
| return mScene->GetBlenderScene(); | return m_scene->GetBlenderScene(); | ||||
| } | |||||
| SCA_IScene *KX_BlenderMaterial::GetScene() const | |||||
| { | |||||
| return m_scene; | |||||
| } | } | ||||
| void KX_BlenderMaterial::ReleaseMaterial() | void KX_BlenderMaterial::ReleaseMaterial() | ||||
| { | { | ||||
| if (mBlenderShader) | if (m_blenderShader) | ||||
| mBlenderShader->ReloadMaterial(); | m_blenderShader->ReloadMaterial(); | ||||
| } | } | ||||
| void KX_BlenderMaterial::InitTextures() | void KX_BlenderMaterial::InitTextures() | ||||
| { | { | ||||
| // for each unique material... | // for each unique material... | ||||
| int i; | int i; | ||||
| for (i=0; i<BL_Texture::GetMaxUnits(); i++) { | for (i = 0; i < RAS_Texture::MaxUnits; i++) { | ||||
| if ( mMaterial->mapping[i].mapping & USEENV ) { | MTex *mtex = m_material->mtex[i]; | ||||
| if (!GLEW_ARB_texture_cube_map) { | if (mtex && mtex->tex) { | ||||
| spit("CubeMap textures not supported"); | BL_Texture *texture = new BL_Texture(mtex); | ||||
| continue; | m_textures[i] = texture; | ||||
| } | |||||
| if (!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) ) | |||||
| spit("unable to initialize image("<<i<<") in "<< | |||||
| mMaterial->matname<< ", image will not be available"); | |||||
| } | |||||
| /* If we're using glsl materials, the textures are handled by bf_gpu, so don't load them twice! | |||||
| * However, if we're using a custom shader, then we still need to load the textures ourselves. */ | |||||
| else if (!mMaterial->glslmat || mShader) { | |||||
| if ( mMaterial->img[i] ) { | |||||
| if ( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 )) | |||||
| spit("unable to initialize image("<<i<<") in "<< | |||||
| mMaterial->matname<< ", image will not be available"); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void KX_BlenderMaterial::OnConstruction() | void KX_BlenderMaterial::OnConstruction() | ||||
| { | { | ||||
| if (mConstructed) | if (m_constructed) { | ||||
| // when material are reused between objects | // when material are reused between objects | ||||
| return; | return; | ||||
| } | |||||
| if (mMaterial->glslmat) | |||||
| SetBlenderGLSLShader(); | |||||
| InitTextures(); | SetBlenderGLSLShader(); | ||||
| mBlendFunc[0] =0; | m_blendFunc[0] = 0; | ||||
| mBlendFunc[1] =0; | m_blendFunc[1] = 0; | ||||
| mConstructed = true; | m_constructed = true; | ||||
| } | } | ||||
| void KX_BlenderMaterial::EndFrame() | void KX_BlenderMaterial::EndFrame(RAS_IRasterizer *rasty) | ||||
| { | { | ||||
| if (mLastBlenderShader) { | rasty->SetAlphaBlend(GPU_BLEND_SOLID); | ||||
| mLastBlenderShader->SetProg(false); | RAS_Texture::DesactiveTextures(); | ||||
| mLastBlenderShader = NULL; | |||||
| } | |||||
| if (mLastShader) { | |||||
| mLastShader->SetProg(false); | |||||
| mLastShader = NULL; | |||||
| } | |||||
| } | } | ||||
| void KX_BlenderMaterial::OnExit() | void KX_BlenderMaterial::OnExit() | ||||
| { | { | ||||
| if ( mShader ) { | if (m_shader) { | ||||
| //note, the shader here is allocated, per unique material | delete m_shader; | ||||
| //and this function is called per face | m_shader = NULL; | ||||
| if (mShader == mLastShader) { | |||||
| mShader->SetProg(false); | |||||
| mLastShader = NULL; | |||||
| } | |||||
| delete mShader; | |||||
| mShader = 0; | |||||
| } | } | ||||
| if (m_blenderShader) { | |||||
| if ( mBlenderShader ) { | delete m_blenderShader; | ||||
| if (mBlenderShader == mLastBlenderShader) { | m_blenderShader = NULL; | ||||
| mBlenderShader->SetProg(false); | |||||
| mLastBlenderShader = NULL; | |||||
| } | |||||
| delete mBlenderShader; | |||||
| mBlenderShader = 0; | |||||
| } | } | ||||
| BL_Texture::ActivateFirst(); | /* used to call with 'm_material->tface' but this can be a freed array, | ||||
| for (int i=0; i<BL_Texture::GetMaxUnits(); i++) { | |||||
| if (!mTextures[i].Ok()) continue; | |||||
| BL_Texture::ActivateUnit(i); | |||||
| mTextures[i].DeleteTex(); | |||||
| mTextures[i].DisableUnit(); | |||||
| } | |||||
| /* used to call with 'mMaterial->tface' but this can be a freed array, | |||||
| * see: [#30493], so just call with NULL, this is best since it clears | * see: [#30493], so just call with NULL, this is best since it clears | ||||
| * the 'lastface' pointer in GPU too - campbell */ | * the 'lastface' pointer in GPU too - campbell */ | ||||
| GPU_set_tpage(NULL, 1, mMaterial->alphablend); | GPU_set_tpage(NULL, 1, m_alphablend); | ||||
| } | } | ||||
| void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) | void KX_BlenderMaterial::SetShaderData(RAS_IRasterizer *ras) | ||||
| { | { | ||||
| MT_assert(GLEW_ARB_shader_objects && mShader); | BLI_assert(m_shader); | ||||
| int i; | int i; | ||||
| if ( !enable || !mShader->Ok() ) { | |||||
| // frame cleanup. | |||||
| if (mShader == mLastShader) { | |||||
| mShader->SetProg(false); | |||||
| mLastShader = NULL; | |||||
| } | |||||
| ras->SetAlphaBlend(TF_SOLID); | m_shader->SetProg(true); | ||||
| BL_Texture::DisableAllTextures(); | |||||
| return; | |||||
| } | |||||
| BL_Texture::DisableAllTextures(); | m_shader->ApplyShader(); | ||||
| mShader->SetProg(true); | |||||
| mLastShader = mShader; | |||||
| BL_Texture::ActivateFirst(); | |||||
| mShader->ApplyShader(); | /** We make sure that all gpu textures are the same in material textures here | ||||
| * than in gpu material. This is dones in a separated loop because the texture | |||||
| * regeneration can overide bind settings of the previous texture. | |||||
| */ | |||||
| for (i = 0; i < RAS_Texture::MaxUnits; i++) { | |||||
| if (m_textures[i] && m_textures[i]->Ok()) { | |||||
| m_textures[i]->CheckValidTexture(); | |||||
| } | |||||
| } | |||||
| // for each enabled unit | // for each enabled unit | ||||
| for (i=0; i<BL_Texture::GetMaxUnits(); i++) { | for (i = 0; i < RAS_Texture::MaxUnits; i++) { | ||||
| if (!mTextures[i].Ok()) continue; | if (m_textures[i] && m_textures[i]->Ok()) { | ||||
| mTextures[i].ActivateTexture(); | m_textures[i]->ActivateTexture(i); | ||||
| mTextures[0].SetMapping(mMaterial->mapping[i].mapping); | } | ||||
| } | } | ||||
| if (!mUserDefBlend) { | if (!m_userDefBlend) { | ||||
| ras->SetAlphaBlend(mMaterial->alphablend); | ras->SetAlphaBlend(m_alphablend); | ||||
| } | } | ||||
| else { | else { | ||||
| ras->SetAlphaBlend(TF_SOLID); | ras->SetAlphaBlend(GPU_BLEND_SOLID); | ||||
| ras->SetAlphaBlend(-1); // indicates custom mode | ras->SetAlphaBlend(-1); // indicates custom mode | ||||
| // tested to be valid enums | // tested to be valid enums | ||||
| glEnable(GL_BLEND); | ras->Enable(RAS_IRasterizer::RAS_BLEND); | ||||
| glBlendFunc(mBlendFunc[0], mBlendFunc[1]); | ras->SetBlendFunc((RAS_IRasterizer::BlendFunc)m_blendFunc[0], (RAS_IRasterizer::BlendFunc)m_blendFunc[1]); | ||||
| } | } | ||||
| } | } | ||||
| void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras) | void KX_BlenderMaterial::SetBlenderShaderData(RAS_IRasterizer *ras) | ||||
| { | { | ||||
| if ( !enable || !mBlenderShader->Ok() ) { | // Don't set the alpha blend here because ActivateMeshSlot do it. | ||||
| ras->SetAlphaBlend(TF_SOLID); | m_blenderShader->SetProg(true, ras->GetTime(), ras); | ||||
| // frame cleanup. | |||||
| if (mLastBlenderShader) { | |||||
| mLastBlenderShader->SetProg(false); | |||||
| mLastBlenderShader= NULL; | |||||
| } | |||||
| else | |||||
| BL_Texture::DisableAllTextures(); | |||||
| return; | |||||
| } | |||||
| if (!mBlenderShader->Equals(mLastBlenderShader)) { | |||||
| ras->SetAlphaBlend(mMaterial->alphablend); | |||||
| if (mLastBlenderShader) | |||||
| mLastBlenderShader->SetProg(false); | |||||
| else | |||||
| BL_Texture::DisableAllTextures(); | |||||
| mBlenderShader->SetProg(true, ras->GetTime(), ras); | |||||
| mLastBlenderShader= mBlenderShader; | |||||
| } | |||||
| } | } | ||||
| void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) | void KX_BlenderMaterial::ActivateShaders(RAS_IRasterizer *rasty) | ||||
| { | { | ||||
| BL_Texture::DisableAllTextures(); | SetShaderData(rasty); | ||||
| if ( !enable ) { | |||||
| ras->SetAlphaBlend(TF_SOLID); | |||||
| return; | |||||
| } | |||||
| BL_Texture::ActivateFirst(); | |||||
| if ( mMaterial->IdMode == DEFAULT_BLENDER ) { | |||||
| ras->SetAlphaBlend(mMaterial->alphablend); | |||||
| return; | |||||
| } | |||||
| if ( mMaterial->IdMode == TEXFACE ) { | |||||
| // no material connected to the object | |||||
| if ( mTextures[0].Ok() ) { | |||||
| mTextures[0].ActivateTexture(); | |||||
| mTextures[0].setTexEnv(0, true); | |||||
| mTextures[0].SetMapping(mMaterial->mapping[0].mapping); | |||||
| ras->SetAlphaBlend(mMaterial->alphablend); | |||||
| } | |||||
| return; | |||||
| } | |||||
| int mode = 0,i=0; | if (IsWire()) { | ||||
| for (i=0; i<BL_Texture::GetMaxUnits(); i++) { | rasty->SetCullFace(false); | ||||
| if ( !mTextures[i].Ok() ) continue; | |||||
| mTextures[i].ActivateTexture(); | |||||
| mTextures[i].setTexEnv(mMaterial); | |||||
| mode = mMaterial->mapping[i].mapping; | |||||
| if (mode &USEOBJ) | |||||
| setObjectMatrixData(i, ras); | |||||
| else | |||||
| mTextures[i].SetMapping(mode); | |||||
| if (!(mode &USEOBJ)) | |||||
| setTexMatrixData( i ); | |||||
| } | } | ||||
| else if (IsCullFace()) { | |||||
| if (!mUserDefBlend) { | rasty->SetCullFace(true); | ||||
| ras->SetAlphaBlend(mMaterial->alphablend); | |||||
| } | } | ||||
| else { | else { | ||||
| ras->SetAlphaBlend(TF_SOLID); | rasty->SetCullFace(false); | ||||
| ras->SetAlphaBlend(-1); // indicates custom mode | |||||
| glEnable(GL_BLEND); | |||||
| glBlendFunc(mBlendFunc[0], mBlendFunc[1]); | |||||
| } | } | ||||
| ActivateGLMaterials(rasty); | |||||
| ActivateTexGen(rasty); | |||||
| } | } | ||||
| void | void KX_BlenderMaterial::ActivateBlenderShaders(RAS_IRasterizer *rasty) | ||||
| KX_BlenderMaterial::ActivatShaders( | |||||
| RAS_IRasterizer* rasty, | |||||
| TCachingInfo& cachingInfo)const | |||||
| { | { | ||||
| KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); | SetBlenderShaderData(rasty); | ||||
| // reset... | |||||
| if (tmp->mMaterial->IsShared()) | |||||
| cachingInfo =0; | |||||
| if (mLastBlenderShader) { | if (IsWire()) { | ||||
| mLastBlenderShader->SetProg(false); | rasty->SetCullFace(false); | ||||
| mLastBlenderShader= NULL; | |||||
| } | } | ||||
| else if (IsCullFace()) { | |||||
| if (GetCachingInfo() != cachingInfo) { | rasty->SetCullFace(true); | ||||
| } | |||||
| if (!cachingInfo) | else { | ||||
| tmp->setShaderData(false, rasty); | rasty->SetCullFace(false); | ||||
| cachingInfo = GetCachingInfo(); | |||||
| if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) | |||||
| tmp->setShaderData(true, rasty); | |||||
| else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !rasty->GetUsingOverrideShader()) | |||||
| tmp->setShaderData(true, rasty); | |||||
| else | |||||
| tmp->setShaderData(false, rasty); | |||||
| if (mMaterial->ras_mode &TWOSIDED) | |||||
| rasty->SetCullFace(false); | |||||
| else | |||||
| rasty->SetCullFace(true); | |||||
| if ((mMaterial->ras_mode &WIRE) || | |||||
| (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) | |||||
| { | |||||
| if (mMaterial->ras_mode &WIRE) | |||||
| rasty->SetCullFace(false); | |||||
| rasty->SetLines(true); | |||||
| } | |||||
| else | |||||
| rasty->SetLines(false); | |||||
| ActivatGLMaterials(rasty); | |||||
| ActivateTexGen(rasty); | |||||
| } | } | ||||
| //ActivatGLMaterials(rasty); | ActivateGLMaterials(rasty); | ||||
| //ActivateTexGen(rasty); | m_blenderShader->SetAttribs(rasty); | ||||
| } | } | ||||
| void | void KX_BlenderMaterial::Activate(RAS_IRasterizer *rasty) | ||||
| KX_BlenderMaterial::ActivateBlenderShaders( | |||||
| RAS_IRasterizer* rasty, | |||||
| TCachingInfo& cachingInfo)const | |||||
| { | { | ||||
| KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); | if (m_shader && m_shader->Ok()) { | ||||
| ActivateShaders(rasty); | |||||
| if (mLastShader) { | } | ||||
| mLastShader->SetProg(false); | else if (m_blenderShader && m_blenderShader->Ok()) { | ||||
| mLastShader= NULL; | ActivateBlenderShaders(rasty); | ||||
| } | } | ||||
| } | |||||
| if (GetCachingInfo() != cachingInfo) { | void KX_BlenderMaterial::Desactivate(RAS_IRasterizer *rasty) | ||||
| if (!cachingInfo) | { | ||||
| tmp->setBlenderShaderData(false, rasty); | if (m_shader && m_shader->Ok()) { | ||||
| m_shader->SetProg(false); | |||||
| cachingInfo = GetCachingInfo(); | for (unsigned short i = 0; i < RAS_Texture::MaxUnits; i++) { | ||||
| if (m_textures[i] && m_textures[i]->Ok()) { | |||||
| if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) | m_textures[i]->DisableTexture(); | ||||
| tmp->setBlenderShaderData(true, rasty); | } | ||||
| else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !rasty->GetUsingOverrideShader()) | |||||
| tmp->setBlenderShaderData(true, rasty); | |||||
| else | |||||
| tmp->setBlenderShaderData(false, rasty); | |||||
| if (mMaterial->ras_mode &TWOSIDED) | |||||
| rasty->SetCullFace(false); | |||||
| else | |||||
| rasty->SetCullFace(true); | |||||
| if ((mMaterial->ras_mode &WIRE) || | |||||
| (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) | |||||
| { | |||||
| if (mMaterial->ras_mode &WIRE) | |||||
| rasty->SetCullFace(false); | |||||
| rasty->SetLines(true); | |||||
| } | } | ||||
| else | |||||
| rasty->SetLines(false); | |||||
| ActivatGLMaterials(rasty); | |||||
| mBlenderShader->SetAttribs(rasty, mMaterial); | |||||
| } | } | ||||
| else if (m_blenderShader && m_blenderShader->Ok()) { | |||||
| m_blenderShader->SetProg(false); | |||||
| } | |||||
| // Make sure no one will use the attributs set by this material. | |||||
| rasty->ClearTexCoords(); | |||||
| rasty->ClearAttribs(); | |||||
| } | } | ||||
| void | bool KX_BlenderMaterial::UseInstancing() const | ||||
| KX_BlenderMaterial::ActivateMat( | |||||
| RAS_IRasterizer* rasty, | |||||
| TCachingInfo& cachingInfo | |||||
| )const | |||||
| { | { | ||||
| KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); | if (m_shader && m_shader->Ok()) { | ||||
| return false; | |||||
| if (mLastShader) { | |||||
| mLastShader->SetProg(false); | |||||
| mLastShader= NULL; | |||||
| } | } | ||||
| else if (m_blenderShader) { | |||||
| if (mLastBlenderShader) { | return m_blenderShader->UseInstancing(); | ||||
| mLastBlenderShader->SetProg(false); | |||||
| mLastBlenderShader= NULL; | |||||
| } | } | ||||
| // The material is in conversion, we use the blender material flag then. | |||||
| return m_material->shade_flag & MA_INSTANCING; | |||||
| } | |||||
| if (GetCachingInfo() != cachingInfo) { | void KX_BlenderMaterial::ActivateInstancing(RAS_IRasterizer *rasty, void *matrixoffset, void *positionoffset, void *coloroffset, unsigned int stride) | ||||
| if (!cachingInfo) | { | ||||
| tmp->setTexData( false,rasty ); | if (m_blenderShader) { | ||||
| m_blenderShader->ActivateInstancing(matrixoffset, positionoffset, coloroffset, stride); | |||||
| cachingInfo = GetCachingInfo(); | |||||
| if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) | |||||
| tmp->setTexData( true,rasty ); | |||||
| else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !rasty->GetUsingOverrideShader()) | |||||
| tmp->setTexData(true, rasty); | |||||
| else | |||||
| tmp->setTexData( false,rasty); | |||||
| if (mMaterial->ras_mode &TWOSIDED) | |||||
| rasty->SetCullFace(false); | |||||
| else | |||||
| rasty->SetCullFace(true); | |||||
| if ((mMaterial->ras_mode &WIRE) || | |||||
| (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) | |||||
| { | |||||
| if (mMaterial->ras_mode &WIRE) | |||||
| rasty->SetCullFace(false); | |||||
| rasty->SetLines(true); | |||||
| } | |||||
| else | |||||
| rasty->SetLines(false); | |||||
| ActivatGLMaterials(rasty); | |||||
| ActivateTexGen(rasty); | |||||
| } | } | ||||
| //ActivatGLMaterials(rasty); | /* Because the geometry instancing use setting for all instances we use the original alpha blend. | ||||
| //ActivateTexGen(rasty); | * This requierd that the user use "alpha blend" mode if he will use mutate object color alpha. | ||||
| */ | |||||
| rasty->SetAlphaBlend(m_alphablend); | |||||
| } | } | ||||
| bool | void KX_BlenderMaterial::DesactivateInstancing() | ||||
| KX_BlenderMaterial::Activate( | |||||
| RAS_IRasterizer* rasty, | |||||
| TCachingInfo& cachingInfo | |||||
| )const | |||||
| { | { | ||||
| if (GLEW_ARB_shader_objects && (mShader && mShader->Ok())) { | if (m_blenderShader) { | ||||
| if ((mPass++) < mShader->getNumPass() ) { | m_blenderShader->DesactivateInstancing(); | ||||
| ActivatShaders(rasty, cachingInfo); | |||||
| return true; | |||||
| } | |||||
| else { | |||||
| if (mShader == mLastShader) { | |||||
| mShader->SetProg(false); | |||||
| mLastShader = NULL; | |||||
| } | |||||
| mPass = 0; | |||||
| return false; | |||||
| } | |||||
| } | |||||
| else if ( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) { | |||||
| if (mPass++ == 0) { | |||||
| ActivateBlenderShaders(rasty, cachingInfo); | |||||
| return true; | |||||
| } | |||||
| else { | |||||
| mPass = 0; | |||||
| return false; | |||||
| } | |||||
| } | |||||
| else { | |||||
| if (mPass++ == 0) { | |||||
| ActivateMat(rasty, cachingInfo); | |||||
| return true; | |||||
| } | |||||
| else { | |||||
| mPass = 0; | |||||
| return false; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| if (!RAS_IPolyMaterial::UsesLighting(rasty)) | if (!RAS_IPolyMaterial::UsesLighting(rasty)) | ||||
| return false; | return false; | ||||
| if (mShader && mShader->Ok()) | if (m_shader && m_shader->Ok()) | ||||
| return true; | return true; | ||||
| else if (mBlenderShader && mBlenderShader->Ok()) | else if (m_blenderShader && m_blenderShader->Ok()) | ||||
| return false; | return false; | ||||
| else | else | ||||
| return true; | return true; | ||||
| } | } | ||||
| void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const | void KX_BlenderMaterial::ActivateMeshSlot(RAS_MeshSlot *ms, RAS_IRasterizer *rasty) | ||||
| { | { | ||||
| if (mShader && GLEW_ARB_shader_objects) { | if (m_shader && m_shader->Ok()) { | ||||
| mShader->Update(ms, rasty); | m_shader->Update(rasty, ms); | ||||
| m_shader->ApplyShader(); | |||||
| } | } | ||||
| else if (mBlenderShader && GLEW_ARB_shader_objects) { | else if (m_blenderShader) { | ||||
| int alphablend; | m_blenderShader->Update(ms, rasty); | ||||
| mBlenderShader->Update(ms, rasty); | |||||
| /* we do blend modes here, because they can change per object | /* we do blend modes here, because they can change per object | ||||
| * with the same material due to obcolor/obalpha */ | * with the same material due to obcolor/obalpha */ | ||||
| alphablend = mBlenderShader->GetAlphaBlend(); | int alphablend = m_blenderShader->GetAlphaBlend(); | ||||
| if (ELEM(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID) | if (ELEM(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && m_alphablend != GEMAT_SOLID) | ||||
| alphablend = mMaterial->alphablend; | alphablend = m_alphablend; | ||||
| rasty->SetAlphaBlend(alphablend); | rasty->SetAlphaBlend(alphablend); | ||||
| } | } | ||||
| } | } | ||||
| void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const | void KX_BlenderMaterial::ActivateGLMaterials(RAS_IRasterizer *rasty) const | ||||
| { | { | ||||
| if (mShader || !mBlenderShader) { | if (m_shader || !m_blenderShader) { | ||||
| rasty->SetSpecularity( | rasty->SetSpecularity(m_material->specr * m_material->spec, m_material->specg * m_material->spec, | ||||
| mMaterial->speccolor[0]*mMaterial->spec_f, | m_material->specb * m_material->spec, m_material->spec); | ||||
| mMaterial->speccolor[1]*mMaterial->spec_f, | rasty->SetShinyness(((float)m_material->har) / 4.0f); | ||||
| mMaterial->speccolor[2]*mMaterial->spec_f, | rasty->SetDiffuse(m_material->r * m_material->ref + m_material->emit, m_material->g * m_material->ref + m_material->emit, | ||||
| mMaterial->spec_f | m_material->b * m_material->ref + m_material->emit, 1.0f); | ||||
| ); | rasty->SetEmissive(m_material->r * m_material->emit, m_material->g * m_material->emit, | ||||
| m_material->b * m_material->emit, 1.0f); | |||||
| rasty->SetShinyness( mMaterial->hard ); | rasty->SetAmbient(m_material->amb); | ||||
| rasty->SetDiffuse( | |||||
| mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, | |||||
| mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit, | |||||
| mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit, | |||||
| 1.0f); | |||||
| rasty->SetEmissive( | |||||
| mMaterial->matcolor[0]*mMaterial->emit, | |||||
| mMaterial->matcolor[1]*mMaterial->emit, | |||||
| mMaterial->matcolor[2]*mMaterial->emit, | |||||
| 1.0f ); | |||||
| rasty->SetAmbient(mMaterial->amb); | |||||
| } | } | ||||
| if (mMaterial->material) | rasty->SetPolygonOffset(-m_material->zoffs, 0.0f); | ||||
| rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0f); | |||||
| } | } | ||||
| void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const | void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const | ||||
| { | { | ||||
| if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED || | if (m_shader->GetAttribute() == BL_Shader::SHD_TANGENT) { | ||||
| (ras->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !ras->GetUsingOverrideShader())) { | RAS_IRasterizer::TexCoGenList attribs(2); | ||||
| ras->SetAttribNum(0); | attribs[0] = RAS_IRasterizer::RAS_TEXCO_DISABLE; | ||||
| if (mShader && GLEW_ARB_shader_objects) { | attribs[1] = RAS_IRasterizer::RAS_TEXTANGENT; | ||||
| if (mShader->GetAttribute() == BL_Shader::SHD_TANGENT) { | |||||
| ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, 0); | |||||
| ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, 1); | |||||
| ras->SetAttribNum(2); | |||||
| } | |||||
| } | |||||
| ras->SetTexCoordNum(mMaterial->num_enabled); | ras->SetAttribs(attribs); | ||||
| for (int i=0; i<BL_Texture::GetMaxUnits(); i++) { | |||||
| int mode = mMaterial->mapping[i].mapping; | |||||
| if ( mode &(USEREFL|USEOBJ)) | |||||
| ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i); | |||||
| else if (mode &USEORCO) | |||||
| ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_ORCO, i); | |||||
| else if (mode &USENORM) | |||||
| ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i); | |||||
| else if (mode &USEUV) | |||||
| ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV, i); | |||||
| else if (mode &USETANG) | |||||
| ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i); | |||||
| else | |||||
| ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i); | |||||
| } | |||||
| } | } | ||||
| } | |||||
| void KX_BlenderMaterial::setTexMatrixData(int i) | RAS_IRasterizer::TexCoGenList texcos(RAS_Texture::MaxUnits); | ||||
| { | for (int i = 0; i < RAS_Texture::MaxUnits; i++) { | ||||
| glMatrixMode(GL_TEXTURE); | RAS_Texture *texture = m_textures[i]; | ||||
| glLoadIdentity(); | /* Here textures can return false to Ok() because we're looking only at | ||||
| * texture attributs and not texture bind id like for the binding and | |||||
| if ( GLEW_ARB_texture_cube_map && | * unbinding of textures. A NULL BL_Texture means that the cooresponding | ||||
| mTextures[i].GetTextureType() == GL_TEXTURE_CUBE_MAP_ARB && | * mtex is NULL too (see InitTextures).*/ | ||||
| mMaterial->mapping[i].mapping & USEREFL) { | if (texture) { | ||||
| glScalef( | MTex *mtex = texture->GetMTex(); | ||||
| mMaterial->mapping[i].scale[0], | if (mtex->texco & (TEXCO_OBJECT | TEXCO_REFL)) { | ||||
| -mMaterial->mapping[i].scale[1], | texcos[i] = RAS_IRasterizer::RAS_TEXCO_GEN; | ||||
| -mMaterial->mapping[i].scale[2] | } | ||||
| ); | else if (mtex->texco & (TEXCO_ORCO | TEXCO_GLOB)) { | ||||
| } | texcos[i] = RAS_IRasterizer::RAS_TEXCO_ORCO; | ||||
| else | } | ||||
| { | else if (mtex->texco & TEXCO_UV) { | ||||
| glScalef( | texcos[i] = RAS_IRasterizer::RAS_TEXCO_UV; | ||||
| mMaterial->mapping[i].scale[0], | } | ||||
| mMaterial->mapping[i].scale[1], | else if (mtex->texco & TEXCO_NORM) { | ||||
| mMaterial->mapping[i].scale[2] | texcos[i] = RAS_IRasterizer::RAS_TEXCO_NORM; | ||||
| ); | } | ||||
| else if (mtex->texco & TEXCO_TANGENT) { | |||||
| texcos[i] = RAS_IRasterizer::RAS_TEXTANGENT; | |||||
| } | |||||
| } | |||||
| else { | |||||
| texcos[i] = RAS_IRasterizer::RAS_TEXCO_DISABLE; | |||||
| } | |||||
| } | } | ||||
| glTranslatef( | ras->SetTexCoords(texcos); | ||||
| mMaterial->mapping[i].offsets[0], | |||||
| mMaterial->mapping[i].offsets[1], | |||||
| mMaterial->mapping[i].offsets[2] | |||||
| ); | |||||
| glMatrixMode(GL_MODELVIEW); | |||||
| } | |||||
| static void GetProjPlane(BL_Material *mat, int index,int num, float*param) | |||||
| { | |||||
| param[0]=param[1]=param[2]=param[3]=0.f; | |||||
| if ( mat->mapping[index].projplane[num] == PROJX ) | |||||
| param[0] = 1.f; | |||||
| else if ( mat->mapping[index].projplane[num] == PROJY ) | |||||
| param[1] = 1.f; | |||||
| else if ( mat->mapping[index].projplane[num] == PROJZ) | |||||
| param[2] = 1.f; | |||||
| } | } | ||||
| void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras) | void KX_BlenderMaterial::UpdateIPO( | ||||
| MT_Vector4 rgba, | |||||
| MT_Vector3 specrgb, | |||||
| MT_Scalar hard, | |||||
| MT_Scalar spec, | |||||
| MT_Scalar ref, | |||||
| MT_Scalar emit, | |||||
| MT_Scalar ambient, | |||||
| MT_Scalar alpha, | |||||
| MT_Scalar specalpha) | |||||
| { | { | ||||
| KX_GameObject *obj = | // only works one deep now | ||||
| (KX_GameObject*) | |||||
| mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame); | |||||
| if (!obj) return; | |||||
| glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); | |||||
| glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); | |||||
| glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); | |||||
| GLenum plane = GL_EYE_PLANE; | |||||
| // figure plane gen | |||||
| float proj[4] = {0.f,0.f,0.f,0.f}; | |||||
| GetProjPlane(mMaterial, i, 0, proj); | |||||
| glTexGenfv(GL_S, plane, proj); | |||||
| GetProjPlane(mMaterial, i, 1, proj); | |||||
| glTexGenfv(GL_T, plane, proj); | |||||
| GetProjPlane(mMaterial, i, 2, proj); | |||||
| glTexGenfv(GL_R, plane, proj); | |||||
| glEnable(GL_TEXTURE_GEN_S); | |||||
| glEnable(GL_TEXTURE_GEN_T); | |||||
| glEnable(GL_TEXTURE_GEN_R); | |||||
| const MT_Matrix4x4& mvmat = ras->GetViewMatrix(); | |||||
| glMatrixMode(GL_TEXTURE); | |||||
| glLoadIdentity(); | |||||
| glScalef( | |||||
| mMaterial->mapping[i].scale[0], | |||||
| mMaterial->mapping[i].scale[1], | |||||
| mMaterial->mapping[i].scale[2] | |||||
| ); | |||||
| MT_Point3 pos = obj->NodeGetWorldPosition(); | |||||
| MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f); | |||||
| MT_Vector4 t = mvmat*matmul; | |||||
| glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) ); | |||||
| glMatrixMode(GL_MODELVIEW); | |||||
| // GLSL Input | |||||
| m_material->specr = (float)(specrgb)[0]; | |||||
| m_material->specg = (float)(specrgb)[1]; | |||||
| m_material->specb = (float)(specrgb)[2]; | |||||
| m_material->r = (float)(rgba[0]); | |||||
| m_material->g = (float)(rgba[1]); | |||||
| m_material->b = (float)(rgba[2]); | |||||
| m_material->alpha = (float)(rgba[3]); | |||||
| m_material->amb = (float)(ambient); | |||||
| m_material->har = (float)(hard); | |||||
| m_material->emit = (float)(emit); | |||||
| m_material->spec = (float)(spec); | |||||
| m_material->ref = (float)(ref); | |||||
| m_material->spectra = (float)specalpha; | |||||
| } | } | ||||
| // ------------------------------------ | const RAS_IRasterizer::AttribLayerList KX_BlenderMaterial::GetAttribLayers(const RAS_MeshObject::LayersInfo& layersInfo) const | ||||
| void KX_BlenderMaterial::UpdateIPO( | |||||
| MT_Vector4 rgba, | |||||
| MT_Vector3 specrgb, | |||||
| MT_Scalar hard, | |||||
| MT_Scalar spec, | |||||
| MT_Scalar ref, | |||||
| MT_Scalar emit, | |||||
| MT_Scalar alpha | |||||
| ) | |||||
| { | { | ||||
| // only works one deep now | if (m_blenderShader && m_blenderShader->Ok()) { | ||||
| return m_blenderShader->GetAttribLayers(layersInfo); | |||||
| } | |||||
| // GLSL Multitexture Input | static const RAS_IRasterizer::AttribLayerList attribLayers; | ||||
| mMaterial->material->specr = mMaterial->speccolor[0] = (float)(specrgb)[0]; | return attribLayers; | ||||
| mMaterial->material->specg = mMaterial->speccolor[1] = (float)(specrgb)[1]; | |||||
| mMaterial->material->specb = mMaterial->speccolor[2] = (float)(specrgb)[2]; | |||||
| mMaterial->material->r = mMaterial->matcolor[0] = (float)(rgba[0]); | |||||
| mMaterial->material->g = mMaterial->matcolor[1] = (float)(rgba[1]); | |||||
| mMaterial->material->b = mMaterial->matcolor[2] = (float)(rgba[2]); | |||||
| mMaterial->material->alpha = mMaterial->alpha = (float)(rgba[3]); | |||||
| mMaterial->material->har = mMaterial->hard = (float)(hard); | |||||
| mMaterial->material->emit = mMaterial->emit = (float)(emit); | |||||
| mMaterial->material->spec = mMaterial->spec_f = (float)(spec); | |||||
| mMaterial->material->ref = mMaterial->ref = (float)(ref); | |||||
| } | } | ||||
| void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) | void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) | ||||
| { | { | ||||
| mScene= static_cast<KX_Scene *>(val); | m_scene = static_cast<KX_Scene *>(val); | ||||
| OnConstruction(); | OnConstruction(); | ||||
| } | } | ||||
| BL_Material *KX_BlenderMaterial::GetBLMaterial() | |||||
| { | |||||
| return mMaterial; | |||||
| } | |||||
| void KX_BlenderMaterial::SetBlenderGLSLShader() | void KX_BlenderMaterial::SetBlenderGLSLShader() | ||||
| { | { | ||||
| if (!mBlenderShader) | if (!m_blenderShader) | ||||
| mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, mLightLayer); | m_blenderShader = new BL_BlenderShader(m_scene, m_material, m_lightLayer); | ||||
| if (!mBlenderShader->Ok()) { | if (!m_blenderShader->Ok()) { | ||||
| delete mBlenderShader; | delete m_blenderShader; | ||||
| mBlenderShader = 0; | m_blenderShader = NULL; | ||||
| } | } | ||||
| } | } | ||||
| std::string KX_BlenderMaterial::GetName() | |||||
| { | |||||
| return m_name; | |||||
| } | |||||
| #ifdef USE_MATHUTILS | #ifdef USE_MATHUTILS | ||||
| #define MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR 1 | #define MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR 1 | ||||
| Context not available. | |||||
| static int mathutils_kxblendermaterial_color_get(BaseMathObject *bmo, int subtype) | static int mathutils_kxblendermaterial_color_get(BaseMathObject *bmo, int subtype) | ||||
| { | { | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial*>BGE_PROXY_REF(bmo->cb_user); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user); | ||||
| if (!self) | if (!self) | ||||
| return -1; | return -1; | ||||
| Material *mat = self->GetBlenderMaterial(); | |||||
| switch (subtype) { | switch (subtype) { | ||||
| case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR: | case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR: | ||||
| { | { | ||||
| copy_v3_v3(bmo->data, self->GetBLMaterial()->matcolor); | bmo->data[0] = mat->r; | ||||
| bmo->data[1] = mat->g; | |||||
| bmo->data[2] = mat->b; | |||||
| break; | break; | ||||
| } | } | ||||
| case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR: | case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR: | ||||
| { | { | ||||
| copy_v3_v3(bmo->data, self->GetBLMaterial()->speccolor); | bmo->data[0] = mat->specr; | ||||
| bmo->data[1] = mat->specg; | |||||
| bmo->data[2] = mat->specb; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| if (!self) | if (!self) | ||||
| return -1; | return -1; | ||||
| Material *mat = self->GetBlenderMaterial(); | |||||
| switch (subtype) { | switch (subtype) { | ||||
| case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR: | case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR: | ||||
| { | { | ||||
| BL_Material *mat = self->GetBLMaterial(); | mat->r = bmo->data[0]; | ||||
| copy_v3_v3(mat->matcolor, bmo->data); | mat->g = bmo->data[1]; | ||||
| mat->material->r = bmo->data[0]; | mat->b = bmo->data[2]; | ||||
| mat->material->g = bmo->data[1]; | |||||
| mat->material->b = bmo->data[2]; | |||||
| break; | break; | ||||
| } | } | ||||
| case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR: | case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR: | ||||
| { | { | ||||
| BL_Material *mat = self->GetBLMaterial(); | mat->specr = bmo->data[0]; | ||||
| copy_v3_v3(mat->speccolor, bmo->data); | mat->specg = bmo->data[1]; | ||||
| mat->material->specr = bmo->data[0]; | mat->specb = bmo->data[2]; | ||||
| mat->material->specg = bmo->data[1]; | |||||
| mat->material->specb = bmo->data[2]; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| #ifdef WITH_PYTHON | #ifdef WITH_PYTHON | ||||
| PyMethodDef KX_BlenderMaterial::Methods[] = | PyMethodDef KX_BlenderMaterial::Methods[] = | ||||
| { | { | ||||
| KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ), | KX_PYMETHODTABLE(KX_BlenderMaterial, getShader), | ||||
| KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ), | KX_PYMETHODTABLE( KX_BlenderMaterial, getTextureBindcode), | ||||
| KX_PYMETHODTABLE( KX_BlenderMaterial, getTextureBindcode ), | KX_PYMETHODTABLE(KX_BlenderMaterial, setBlending), | ||||
| KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ), | {NULL, NULL} //Sentinel | ||||
| {NULL,NULL} //Sentinel | |||||
| }; | }; | ||||
| PyAttributeDef KX_BlenderMaterial::Attributes[] = { | PyAttributeDef KX_BlenderMaterial::Attributes[] = { | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader), | KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex), | KX_PYATTRIBUTE_RO_FUNCTION("textures", KX_BlenderMaterial, pyattr_get_textures), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending), | KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("alpha", KX_BlenderMaterial, pyattr_get_alpha, pyattr_set_alpha), | KX_PYATTRIBUTE_RW_FUNCTION("alpha", KX_BlenderMaterial, pyattr_get_alpha, pyattr_set_alpha), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("hardness", KX_BlenderMaterial, pyattr_get_hardness, pyattr_set_hardness), | KX_PYATTRIBUTE_RW_FUNCTION("hardness", KX_BlenderMaterial, pyattr_get_hardness, pyattr_set_hardness), | ||||
| Context not available. | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", KX_BlenderMaterial, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity), | KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", KX_BlenderMaterial, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("diffuseColor", KX_BlenderMaterial, pyattr_get_diffuse_color, pyattr_set_diffuse_color), | KX_PYATTRIBUTE_RW_FUNCTION("diffuseColor", KX_BlenderMaterial, pyattr_get_diffuse_color, pyattr_set_diffuse_color), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("emit", KX_BlenderMaterial, pyattr_get_emit, pyattr_set_emit), | KX_PYATTRIBUTE_RW_FUNCTION("emit", KX_BlenderMaterial, pyattr_get_emit, pyattr_set_emit), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("ambient", KX_BlenderMaterial, pyattr_get_ambient, pyattr_set_ambient), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("specularAlpha", KX_BlenderMaterial, pyattr_get_specular_alpha, pyattr_set_specular_alpha), | |||||
| { NULL } //Sentinel | KX_PYATTRIBUTE_NULL //Sentinel | ||||
| }; | }; | ||||
| PyTypeObject KX_BlenderMaterial::Type = { | PyTypeObject KX_BlenderMaterial::Type = { | ||||
| Context not available. | |||||
| 0, | 0, | ||||
| 0, | 0, | ||||
| py_base_repr, | py_base_repr, | ||||
| 0,0,0,0,0,0,0,0,0, | 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||||
| Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | ||||
| 0,0,0,0,0,0,0, | 0, 0, 0, 0, 0, 0, 0, | ||||
| Methods, | Methods, | ||||
| 0, | 0, | ||||
| 0, | 0, | ||||
| &PyObjectPlus::Type, | &CValue::Type, | ||||
| 0,0,0,0,0,0, | 0, 0, 0, 0, 0, 0, | ||||
| py_base_new | py_base_new | ||||
| }; | }; | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return self->PygetShader(NULL, NULL); | return self->PygetShader(NULL, NULL); | ||||
| } | } | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | static int kx_blender_material_get_textures_size_cb(void *self_v) | ||||
| { | |||||
| return RAS_Texture::MaxUnits; | |||||
| } | |||||
| static PyObject *kx_blender_material_get_textures_item_cb(void *self_v, int index) | |||||
| { | { | ||||
| KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v); | BL_Texture *tex = (BL_Texture *)((KX_BlenderMaterial *)self_v)->GetTexture(index); | ||||
| return PyLong_FromLong(self->GetMaterialIndex()); | PyObject *item = NULL; | ||||
| if (tex) { | |||||
| item = tex->GetProxy(); | |||||
| } | |||||
| else { | |||||
| item = Py_None; | |||||
| Py_INCREF(Py_None); | |||||
| } | |||||
| return item; | |||||
| } | |||||
| static const std::string kx_blender_material_get_textures_item_name_cb(void *self_v, int index) | |||||
| { | |||||
| BL_Texture *tex = (BL_Texture *)((KX_BlenderMaterial *)self_v)->GetTexture(index); | |||||
| return (tex ? tex->GetName() : ""); | |||||
| } | |||||
| PyObject *KX_BlenderMaterial::pyattr_get_textures(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| return (new CListWrapper(self_v, | |||||
| ((KX_BlenderMaterial *)self_v)->GetProxy(), | |||||
| NULL, | |||||
| kx_blender_material_get_textures_size_cb, | |||||
| kx_blender_material_get_textures_item_cb, | |||||
| kx_blender_material_get_textures_item_name_cb, | |||||
| NULL))->NewProxy(true); | |||||
| } | } | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| unsigned int* bfunc = self->getBlendFunc(); | unsigned int *bfunc = self->GetBlendFunc(); | ||||
| return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]); | return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]); | ||||
| } | } | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_BlenderMaterial::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return PyFloat_FromDouble(self->GetBLMaterial()->alpha); | return PyFloat_FromDouble(self->GetBlenderMaterial()->alpha); | ||||
| } | } | ||||
| int KX_BlenderMaterial::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_BlenderMaterial::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| Context not available. | |||||
| float val = PyFloat_AsDouble(value); | float val = PyFloat_AsDouble(value); | ||||
| if (val == -1 && PyErr_Occurred()) { | if (val == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); | PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name.c_str()); | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| } | } | ||||
| CLAMP(val, 0.0f, 1.0f); | CLAMP(val, 0.0f, 1.0f); | ||||
| BL_Material *mat = self->GetBLMaterial(); | self->GetBlenderMaterial()->alpha = val; | ||||
| mat->alpha = mat->material->alpha = val; | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_specular_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetBlenderMaterial()->spectra); | |||||
| } | |||||
| int KX_BlenderMaterial::pyattr_set_specular_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | |||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| if (val == -1 && PyErr_Occurred()) { | |||||
| PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| CLAMP(val, 0.0f, 1.0f); | |||||
| self->GetBlenderMaterial()->spectra = val; | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| PyObject *KX_BlenderMaterial::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_BlenderMaterial::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return PyLong_FromLong(self->GetBLMaterial()->hard); | return PyLong_FromLong(self->GetBlenderMaterial()->har); | ||||
| } | } | ||||
| int KX_BlenderMaterial::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_BlenderMaterial::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| Context not available. | |||||
| int val = PyLong_AsLong(value); | int val = PyLong_AsLong(value); | ||||
| if (val == -1 && PyErr_Occurred()) { | if (val == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "material.%s = int: KX_BlenderMaterial, expected a int", attrdef->m_name); | PyErr_Format(PyExc_AttributeError, "material.%s = int: KX_BlenderMaterial, expected a int", attrdef->m_name.c_str()); | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| } | } | ||||
| CLAMP(val, 1, 511); | CLAMP(val, 1, 511); | ||||
| BL_Material *mat = self->GetBLMaterial(); | self->GetBlenderMaterial()->har = val; | ||||
| mat->hard = mat->material->har = val; | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_BlenderMaterial::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return PyFloat_FromDouble(self->GetBLMaterial()->spec_f); | return PyFloat_FromDouble(self->GetBlenderMaterial()->spec); | ||||
| } | } | ||||
| int KX_BlenderMaterial::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_BlenderMaterial::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| Context not available. | |||||
| float val = PyFloat_AsDouble(value); | float val = PyFloat_AsDouble(value); | ||||
| if (val == -1 && PyErr_Occurred()) { | if (val == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); | PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name.c_str()); | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| } | } | ||||
| CLAMP(val, 0.0f, 1.0f); | CLAMP(val, 0.0f, 1.0f); | ||||
| BL_Material *mat = self->GetBLMaterial(); | self->GetBlenderMaterial()->spec = val; | ||||
| mat->spec_f = mat->material->spec = val; | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| Context not available. | |||||
| return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR); | return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR); | ||||
| #else | #else | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->speccolor)); | Material *mat = self->GetBlenderMaterial(); | ||||
| return PyColorFromVector(MT_Vector3(mat->specr, mat->specg, mat->specb); | |||||
| #endif | #endif | ||||
| } | } | ||||
| Context not available. | |||||
| if (!PyVecTo(value, color)) | if (!PyVecTo(value, color)) | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| BL_Material *mat = self->GetBLMaterial(); | Material *mat = self->GetBlenderMaterial(); | ||||
| color.getValue(mat->speccolor); | mat->specr = color[0]; | ||||
| mat->material->specr = color[0]; | mat->specg = color[1]; | ||||
| mat->material->specg = color[1]; | mat->specb = color[2]; | ||||
| mat->material->specb = color[2]; | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_BlenderMaterial::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return PyFloat_FromDouble(self->GetBLMaterial()->ref); | return PyFloat_FromDouble(self->GetBlenderMaterial()->ref); | ||||
| } | } | ||||
| int KX_BlenderMaterial::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_BlenderMaterial::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| Context not available. | |||||
| float val = PyFloat_AsDouble(value); | float val = PyFloat_AsDouble(value); | ||||
| if (val == -1 && PyErr_Occurred()) { | if (val == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); | PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name.c_str()); | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| } | } | ||||
| CLAMP(val, 0.0f, 1.0f); | CLAMP(val, 0.0f, 1.0f); | ||||
| BL_Material *mat = self->GetBLMaterial(); | self->GetBlenderMaterial()->ref = val; | ||||
| mat->ref = mat->material->ref = val; | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| Context not available. | |||||
| return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR); | return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR); | ||||
| #else | #else | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->matcolor)); | Material *mat = self->GetBlenderMaterial(); | ||||
| return PyColorFromVector(MT_Vector3(mat->r, mat->g, mat->b)); | |||||
| #endif | #endif | ||||
| } | } | ||||
| Context not available. | |||||
| if (!PyVecTo(value, color)) | if (!PyVecTo(value, color)) | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| BL_Material *mat = self->GetBLMaterial(); | Material *mat = self->GetBlenderMaterial(); | ||||
| color.getValue(mat->matcolor); | mat->r = color[0]; | ||||
| mat->material->r = color[0]; | mat->g = color[1]; | ||||
| mat->material->g = color[1]; | mat->b = color[2]; | ||||
| mat->material->b = color[2]; | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *KX_BlenderMaterial::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_BlenderMaterial::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| return PyFloat_FromDouble(self->GetBLMaterial()->emit); | return PyFloat_FromDouble(self->GetBlenderMaterial()->emit); | ||||
| } | } | ||||
| int KX_BlenderMaterial::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_BlenderMaterial::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| Context not available. | |||||
| float val = PyFloat_AsDouble(value); | float val = PyFloat_AsDouble(value); | ||||
| if (val == -1 && PyErr_Occurred()) { | if (val == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); | PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name.c_str()); | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| } | } | ||||
| CLAMP(val, 0.0f, 2.0f); | CLAMP(val, 0.0f, 2.0f); | ||||
| BL_Material *mat = self->GetBLMaterial(); | self->GetBlenderMaterial()->emit = val; | ||||
| mat->emit = mat->material->emit = val; | return PY_SET_ATTR_SUCCESS; | ||||
| } | |||||
| PyObject *KX_BlenderMaterial::pyattr_get_ambient(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetBlenderMaterial()->amb); | |||||
| } | |||||
| int KX_BlenderMaterial::pyattr_set_ambient(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | |||||
| KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| if (val == -1 && PyErr_Occurred()) { | |||||
| PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| CLAMP(val, 0.0f, 1.0f); | |||||
| self->GetBlenderMaterial()->amb = val; | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v); | KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); | ||||
| PyObject *obj = self->PysetBlending(value, NULL); | PyObject *obj = self->PysetBlending(value, NULL); | ||||
| if (obj) | if (obj) | ||||
| { | { | ||||
| Context not available. | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") | KX_PYMETHODDEF_DOC(KX_BlenderMaterial, getShader, "getShader()") | ||||
| { | { | ||||
| if ( !GLEW_ARB_fragment_shader) { | // returns Py_None on error | ||||
| if (!mModified) | // the calling script will need to check | ||||
| spit("Fragment shaders not supported"); | |||||
| mModified = true; | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| if ( !GLEW_ARB_vertex_shader) { | if (!m_shader) { | ||||
| if (!mModified) | m_shader = new BL_Shader(); | ||||
| spit("Vertex shaders not supported"); | if (!m_shader->GetError()) { | ||||
| // Set the material to use custom shader. | |||||
| mModified = true; | m_flag &= ~RAS_BLENDERGLSL; | ||||
| Py_RETURN_NONE; | m_scene->GetBucketManager()->ReleaseDisplayLists(this); | ||||
| } | |||||
| } | } | ||||
| if (!GLEW_ARB_shader_objects) { | if (!m_shader->GetError()) { | ||||
| if (!mModified) | return m_shader->GetProxy(); | ||||
| spit("GLSL not supported"); | |||||
| mModified = true; | |||||
| Py_RETURN_NONE; | |||||
| } | } | ||||
| // We have a shader but invalid. | |||||
| else { | else { | ||||
| // returns Py_None on error | // decref all references to the object | ||||
| // the calling script will need to check | // then delete it! | ||||
| // We will then go back to fixed functionality | |||||
| if (!mShader && !mModified) { | // for this material | ||||
| mShader = new BL_Shader(); | delete m_shader; /* will handle python de-referencing */ | ||||
| mModified = true; | m_shader = NULL; | ||||
| // Using a custom shader, make sure to initialize textures | |||||
| InitTextures(); | |||||
| } | |||||
| if (mShader && !mShader->GetError()) { | |||||
| m_flag &= ~RAS_BLENDERGLSL; | |||||
| mMaterial->SetSharedMaterial(true); | |||||
| mScene->GetBucketManager()->ReleaseDisplayLists(this); | |||||
| return mShader->GetProxy(); | |||||
| } | |||||
| else { | |||||
| // decref all references to the object | |||||
| // then delete it! | |||||
| // We will then go back to fixed functionality | |||||
| // for this material | |||||
| if (mShader) { | |||||
| delete mShader; /* will handle python de-referencing */ | |||||
| mShader=0; | |||||
| } | |||||
| } | |||||
| Py_RETURN_NONE; | |||||
| } | } | ||||
| PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMaterial, GLSL Error"); | Py_RETURN_NONE; | ||||
| return NULL; | |||||
| } | |||||
| KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") | |||||
| { | |||||
| return PyLong_FromLong(GetMaterialIndex()); | |||||
| } | |||||
| KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) | |||||
| { | |||||
| // TODO: enable python switching | |||||
| return NULL; | |||||
| } | |||||
| KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)") | |||||
| { | |||||
| // TODO: enable python switching | |||||
| return NULL; | |||||
| } | } | ||||
| static const unsigned int GL_array[11] = { | static const unsigned int GL_array[11] = { | ||||
| GL_ZERO, | RAS_IRasterizer::RAS_ZERO, | ||||
| GL_ONE, | RAS_IRasterizer::RAS_ONE, | ||||
| GL_SRC_COLOR, | RAS_IRasterizer::RAS_SRC_COLOR, | ||||
| GL_ONE_MINUS_SRC_COLOR, | RAS_IRasterizer::RAS_ONE_MINUS_SRC_COLOR, | ||||
| GL_DST_COLOR, | RAS_IRasterizer::RAS_DST_COLOR, | ||||
| GL_ONE_MINUS_DST_COLOR, | RAS_IRasterizer::RAS_ONE_MINUS_DST_COLOR, | ||||
| GL_SRC_ALPHA, | RAS_IRasterizer::RAS_SRC_ALPHA, | ||||
| GL_ONE_MINUS_SRC_ALPHA, | RAS_IRasterizer::RAS_ONE_MINUS_SRC_ALPHA, | ||||
| GL_DST_ALPHA, | RAS_IRasterizer::RAS_DST_ALPHA, | ||||
| GL_ONE_MINUS_DST_ALPHA, | RAS_IRasterizer::RAS_ONE_MINUS_DST_ALPHA, | ||||
| GL_SRC_ALPHA_SATURATE | RAS_IRasterizer::RAS_SRC_ALPHA_SATURATE | ||||
| }; | }; | ||||
| KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( bge.logic.src, bge.logic.dest)") | KX_PYMETHODDEF_DOC(KX_BlenderMaterial, setBlending, "setBlending(bge.logic.src, bge.logic.dest)") | ||||
| { | { | ||||
| unsigned int b[2]; | unsigned int b[2]; | ||||
| if (PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1])) | if (PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1])) { | ||||
| { | |||||
| bool value_found[2] = {false, false}; | bool value_found[2] = {false, false}; | ||||
| for (int i=0; i<11; i++) | for (int i = 0; i < 11; i++) { | ||||
| { | |||||
| if (b[0] == GL_array[i]) { | if (b[0] == GL_array[i]) { | ||||
| value_found[0] = true; | value_found[0] = true; | ||||
| mBlendFunc[0] = b[0]; | m_blendFunc[0] = b[0]; | ||||
| } | } | ||||
| if (b[1] == GL_array[i]) { | if (b[1] == GL_array[i]) { | ||||
| value_found[1] = true; | value_found[1] = true; | ||||
| mBlendFunc[1] = b[1]; | m_blendFunc[1] = b[1]; | ||||
| } | |||||
| if (value_found[0] && value_found[1]) { | |||||
| break; | |||||
| } | } | ||||
| if (value_found[0] && value_found[1]) break; | |||||
| } | } | ||||
| if (!value_found[0] || !value_found[1]) { | if (!value_found[0] || !value_found[1]) { | ||||
| PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum."); | PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum."); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| mUserDefBlend = true; | m_userDefBlend = true; | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(KX_BlenderMaterial, getTextureBindcode, "getTextureBindcode(texslot)") | KX_PYMETHODDEF_DOC(KX_BlenderMaterial, getTextureBindcode, "getTextureBindcode(texslot)") | ||||
| { | { | ||||
| ShowDeprecationWarning("material.getTextureBindcode(texslot)", "material.textures[texslot].bindCode"); | |||||
| unsigned int texslot; | unsigned int texslot; | ||||
| if (!PyArg_ParseTuple(args, "i:texslot", &texslot)) { | if (!PyArg_ParseTuple(args, "i:texslot", &texslot)) { | ||||
| PyErr_SetString(PyExc_ValueError, "material.getTextureBindcode(texslot): KX_BlenderMaterial, expected an int."); | PyErr_SetString(PyExc_ValueError, "material.getTextureBindcode(texslot): KX_BlenderMaterial, expected an int."); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| Image *ima = getImage(texslot); | Image *ima = GetTexture(texslot)->GetImage(); | ||||
| if (ima) { | if (ima) { | ||||
| unsigned int *bindcode = ima->bindcode; | unsigned int *bindcode = ima->bindcode; | ||||
| return PyLong_FromLong(*bindcode); | return PyLong_FromLong(*bindcode); | ||||
| Context not available. | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| bool ConvertPythonToMaterial(PyObject *value, KX_BlenderMaterial **material, bool py_none_ok, const char *error_prefix) | |||||
| { | |||||
| if (value == NULL) { | |||||
| PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); | |||||
| *material = NULL; | |||||
| return false; | |||||
| } | |||||
| if (value == Py_None) { | |||||
| *material = NULL; | |||||
| if (py_none_ok) { | |||||
| return true; | |||||
| } | |||||
| else { | |||||
| PyErr_Format(PyExc_TypeError, "%s, expected KX_BlenderMaterial or a KX_BlenderMaterial name, None is invalid", error_prefix); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| if (PyObject_TypeCheck(value, &KX_BlenderMaterial::Type)) { | |||||
| KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(value); | |||||
| /* sets the error */ | |||||
| if (mat == NULL) { | |||||
| PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); | |||||
| return false; | |||||
| } | |||||
| *material = mat; | |||||
| return true; | |||||
| } | |||||
| *material = NULL; | |||||
| if (py_none_ok) { | |||||
| PyErr_Format(PyExc_TypeError, "%s, expect a KX_BlenderMaterial, a string or None", error_prefix); | |||||
| } | |||||
| else { | |||||
| PyErr_Format(PyExc_TypeError, "%s, expect a KX_BlenderMaterial or a string", error_prefix); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| #endif // WITH_PYTHON | #endif // WITH_PYTHON | ||||
| Context not available. | |||||