Blender V2.61 - r43446

KX_PolygonMaterial.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stddef.h>
00034 
00035 #include "KX_PolygonMaterial.h"
00036 
00037 #include "BKE_mesh.h"
00038 #include "BKE_global.h"
00039 #include "BKE_image.h"
00040 
00041 #include "DNA_material_types.h"
00042 #include "DNA_texture_types.h"
00043 #include "DNA_image_types.h"
00044 #include "DNA_meshdata_types.h"
00045 
00046 #include "IMB_imbuf_types.h"
00047 
00048 #include "GPU_draw.h"
00049 
00050 #include "MEM_guardedalloc.h"
00051 
00052 #include "RAS_LightObject.h"
00053 #include "RAS_MaterialBucket.h"
00054 
00055 #include "KX_PyMath.h"
00056 
00057 #define KX_POLYGONMATERIAL_CAPSULE_ID "KX_POLYGONMATERIAL_PTR"
00058 
00059 KX_PolygonMaterial::KX_PolygonMaterial()
00060         : PyObjectPlus(),
00061           RAS_IPolyMaterial(),
00062 
00063     m_tface(NULL),
00064     m_mcol(NULL),
00065     m_material(NULL),
00066 #ifdef WITH_PYTHON
00067     m_pymaterial(NULL),
00068 #endif
00069     m_pass(0)
00070 {
00071 }
00072 
00073 void KX_PolygonMaterial::Initialize(
00074         const STR_String &texname,
00075         Material* ma,
00076         int materialindex,
00077         int tile,
00078         int tilexrep,
00079         int tileyrep,
00080         int alphablend,
00081         bool alpha,
00082         bool zsort,
00083         bool light,
00084         int lightlayer,
00085         struct MTFace* tface,
00086         unsigned int* mcol)
00087 {
00088     RAS_IPolyMaterial::Initialize(
00089                             texname,
00090                             ma?ma->id.name:"",
00091                             materialindex,
00092                             tile,
00093                             tilexrep,
00094                             tileyrep,
00095                             alphablend,
00096                             alpha,
00097                             zsort,
00098                             light,
00099                             (texname && texname != ""?true:false), /* if we have a texture we have image */
00100                             ma?&ma->game:NULL);
00101     m_tface = tface;
00102     m_mcol = mcol;
00103     m_material = ma;
00104 #ifdef WITH_PYTHON
00105     m_pymaterial = 0;
00106 #endif
00107     m_pass = 0;
00108 }
00109 
00110 KX_PolygonMaterial::~KX_PolygonMaterial()
00111 {
00112 #ifdef WITH_PYTHON
00113     if (m_pymaterial)
00114     {
00115         Py_DECREF(m_pymaterial);
00116     }
00117 #endif // WITH_PYTHON
00118 }
00119 
00120 Image *KX_PolygonMaterial::GetBlenderImage() const
00121 {
00122     return (m_tface) ? m_tface->tpage : NULL;
00123 }
00124 
00125 bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const 
00126 {
00127     bool dopass = false;
00128 
00129 #ifdef WITH_PYTHON
00130     if (m_pymaterial)
00131     {
00132         PyObject *pyRasty = PyCapsule_New((void*)rasty, KX_POLYGONMATERIAL_CAPSULE_ID, NULL);   /* new reference */
00133         PyObject *pyCachingInfo = PyCapsule_New((void*) &cachingInfo, KX_POLYGONMATERIAL_CAPSULE_ID, NULL); /* new reference */
00134         PyObject *ret = PyObject_CallMethod(m_pymaterial, (char *)"activate", (char *)"(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy);
00135         if (ret)
00136         {
00137             bool value = PyLong_AsSsize_t(ret);
00138             Py_DECREF(ret);
00139             dopass = value;
00140         }
00141         else
00142         {
00143             PyErr_Print();
00144             PyErr_Clear();
00145             PySys_SetObject( (char *)"last_traceback", NULL);
00146         }
00147     }
00148     else
00149 #endif // WITH_PYTHON
00150     {
00151         switch (m_pass++)
00152         {
00153             case 0:
00154                 DefaultActivate(rasty, cachingInfo);
00155                 dopass = true;
00156                 break;
00157             default:
00158                 m_pass = 0;
00159                 dopass = false;
00160                 break;
00161         }
00162     }
00163     
00164     return dopass;
00165 }
00166 
00167 void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const 
00168 {
00169     if (GetCachingInfo() != cachingInfo)
00170     {
00171         if (!cachingInfo)
00172             GPU_set_tpage(NULL, 0, 0);
00173 
00174         cachingInfo = GetCachingInfo();
00175 
00176         if ((m_drawingmode & RAS_IRasterizer::KX_TEX)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED))
00177         {
00178             Image *ima = (Image*)m_tface->tpage;
00179             GPU_update_image_time(ima, rasty->GetTime());
00180             GPU_set_tpage(m_tface, 1, m_alphablend);
00181         }
00182         else
00183             GPU_set_tpage(NULL, 0, 0);
00184         
00185         if(m_drawingmode & RAS_IRasterizer::KX_BACKCULL)
00186             rasty->SetCullFace(true);
00187         else
00188             rasty->SetCullFace(false);
00189 
00190         if ((m_drawingmode & RAS_IRasterizer::KX_LINES) ||
00191                 (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
00192             rasty->SetLines(true);
00193         else
00194             rasty->SetLines(false);
00195         rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
00196         rasty->SetShinyness(m_shininess);
00197         rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
00198         if (m_material)
00199             rasty->SetPolygonOffset(-m_material->zoffs, 0.0);
00200     }
00201 
00202     //rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
00203     //rasty->SetShinyness(m_shininess);
00204     //rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
00205     //if (m_material)
00206     //  rasty->SetPolygonOffset(-m_material->zoffs, 0.0);
00207 }
00208 
00209 void KX_PolygonMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
00210 {
00211     if (m_material) {
00212         *rgba++ = (unsigned char) (m_material->r*255.0);
00213         *rgba++ = (unsigned char) (m_material->g*255.0);
00214         *rgba++ = (unsigned char) (m_material->b*255.0);
00215         *rgba++ = (unsigned char) (m_material->alpha*255.0);
00216     } else
00217         RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
00218 }
00219 
00220 #ifdef WITH_PYTHON
00221 
00222 //----------------------------------------------------------------------------
00223 //Python
00224 
00225 
00226 PyMethodDef KX_PolygonMaterial::Methods[] = {
00227     KX_PYMETHODTABLE(KX_PolygonMaterial, setCustomMaterial),
00228     KX_PYMETHODTABLE(KX_PolygonMaterial, updateTexture),
00229     KX_PYMETHODTABLE(KX_PolygonMaterial, setTexture),
00230     KX_PYMETHODTABLE(KX_PolygonMaterial, activate),
00231 //  KX_PYMETHODTABLE(KX_PolygonMaterial, setPerPixelLights),
00232     
00233     {NULL,NULL} //Sentinel
00234 };
00235 
00236 PyAttributeDef KX_PolygonMaterial::Attributes[] = {
00237     KX_PYATTRIBUTE_RO_FUNCTION("texture",   KX_PolygonMaterial, pyattr_get_texture),
00238     KX_PYATTRIBUTE_RO_FUNCTION("material",  KX_PolygonMaterial, pyattr_get_material), /* should probably be .name ? */
00239     
00240     KX_PYATTRIBUTE_INT_RW("tile", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tile),
00241     KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep),
00242     KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep),
00243     KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode),    
00244     //KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer),
00245 
00246     KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha),
00247     KX_PYATTRIBUTE_BOOL_RW("zsort", KX_PolygonMaterial, m_zsort),
00248     
00249     KX_PYATTRIBUTE_FLOAT_RW("shininess", 0.0f, 1000.0f, KX_PolygonMaterial, m_shininess),
00250     KX_PYATTRIBUTE_FLOAT_RW("specularity", 0.0f, 1000.0f, KX_PolygonMaterial, m_specularity),
00251     
00252     KX_PYATTRIBUTE_RW_FUNCTION("diffuse", KX_PolygonMaterial, pyattr_get_diffuse, pyattr_set_diffuse),
00253     KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular),    
00254     
00255     KX_PYATTRIBUTE_RO_FUNCTION("tface", KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */
00256     KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */
00257     
00258     /* triangle used to be an attribute, removed for 2.49, nobody should be using it */
00259     { NULL }    //Sentinel
00260 };
00261 
00262 PyTypeObject KX_PolygonMaterial::Type = {
00263     PyVarObject_HEAD_INIT(NULL, 0)
00264     "KX_PolygonMaterial",
00265     sizeof(PyObjectPlus_Proxy),
00266     0,
00267     py_base_dealloc,
00268     0,
00269     0,
00270     0,
00271     0,
00272     py_base_repr,
00273     0,0,0,0,0,0,0,0,0,
00274     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00275     0,0,0,0,0,0,0,
00276     Methods,
00277     0,
00278     0,
00279     &PyObjectPlus::Type,
00280     0,0,0,0,0,0,
00281     py_base_new
00282 };
00283 
00284 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(material)")
00285 {
00286     PyObject *material;
00287     if (PyArg_ParseTuple(args, "O:setCustomMaterial", &material))
00288     {
00289         if (m_pymaterial) {
00290             Py_DECREF(m_pymaterial);
00291         }
00292         m_pymaterial = material;
00293         Py_INCREF(m_pymaterial);
00294         Py_RETURN_NONE;
00295     }
00296     
00297     return NULL;
00298 }
00299 
00300 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rasty)")
00301 {
00302     PyObject *pyrasty, *pytface;
00303     if (PyArg_ParseTuple(args, "O!O!:updateTexture", &PyCapsule_Type, &pytface, &PyCapsule_Type, &pyrasty))
00304     {
00305         MTFace *tface = (MTFace*) PyCapsule_GetPointer(pytface, KX_POLYGONMATERIAL_CAPSULE_ID);
00306         RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCapsule_GetPointer(pyrasty, KX_POLYGONMATERIAL_CAPSULE_ID);
00307         Image *ima = (Image*)tface->tpage;
00308         GPU_update_image_time(ima, rasty->GetTime());
00309 
00310         Py_RETURN_NONE;
00311     }
00312     
00313     return NULL;
00314 }
00315 
00316 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)")
00317 {
00318     PyObject *pytface;
00319     if (PyArg_ParseTuple(args, "O!:setTexture", &PyCapsule_Type, &pytface))
00320     {
00321         MTFace *tface = (MTFace*) PyCapsule_GetPointer(pytface, KX_POLYGONMATERIAL_CAPSULE_ID);
00322         GPU_set_tpage(tface, 1, m_alphablend);
00323         Py_RETURN_NONE;
00324     }
00325     
00326     return NULL;
00327 }
00328 
00329 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)")
00330 {
00331     PyObject *pyrasty, *pyCachingInfo;
00332     if (PyArg_ParseTuple(args, "O!O!:activate", &PyCapsule_Type, &pyrasty, &PyCapsule_Type, &pyCachingInfo))
00333     {
00334         RAS_IRasterizer *rasty = static_cast<RAS_IRasterizer*>(PyCapsule_GetPointer(pyrasty, KX_POLYGONMATERIAL_CAPSULE_ID));
00335         TCachingInfo *cachingInfo = static_cast<TCachingInfo*>(PyCapsule_GetPointer(pyCachingInfo, KX_POLYGONMATERIAL_CAPSULE_ID));
00336         if (rasty && cachingInfo)
00337         {
00338             DefaultActivate(rasty, *cachingInfo);
00339             Py_RETURN_NONE;
00340         }
00341     }
00342     
00343     return NULL;
00344 }
00345 
00346 PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00347 {
00348     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00349     return PyUnicode_From_STR_String(self->m_texturename);
00350 }
00351 
00352 PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00353 {
00354     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00355     return PyUnicode_From_STR_String(self->m_materialname);
00356 }
00357 
00358 /* this does not seem useful */
00359 PyObject* KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00360 {
00361     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00362     return PyCapsule_New(self->m_tface, KX_POLYGONMATERIAL_CAPSULE_ID, NULL);
00363 }
00364 
00365 PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00366 {
00367     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00368     int bindcode= 0;
00369     if (self->m_tface && self->m_tface->tpage)
00370         bindcode= self->m_tface->tpage->bindcode;
00371     
00372     return PyLong_FromSsize_t(bindcode);
00373 }
00374 
00375 
00376 PyObject* KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00377 {
00378     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00379     return PyObjectFrom(self->m_diffuse);
00380 }
00381 
00382 int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00383 {
00384     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00385     MT_Vector3 vec;
00386     
00387     if (!PyVecTo(value, vec))
00388         return PY_SET_ATTR_FAIL;
00389     
00390     self->m_diffuse= vec;
00391     return PY_SET_ATTR_SUCCESS;
00392 }
00393 
00394 PyObject* KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00395 {
00396     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00397     return PyObjectFrom(self->m_specular);
00398 }
00399 
00400 int KX_PolygonMaterial::pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00401 {
00402     KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
00403     MT_Vector3 vec;
00404     
00405     if (!PyVecTo(value, vec))
00406         return PY_SET_ATTR_FAIL;
00407     
00408     self->m_specular= vec;
00409     return PY_SET_ATTR_SUCCESS;
00410 }
00411 
00412 #endif // WITH_PYTHON