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