Blender V2.61 - r43446
|
00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of VideoTexture library 00004 00005 Copyright (c) 2007 The Zdeno Ash Miklas 00006 00007 This program is free software; you can redistribute it and/or modify it under 00008 the terms of the GNU Lesser General Public License as published by the Free Software 00009 Foundation; either version 2 of the License, or (at your option) any later 00010 version. 00011 00012 This program is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00014 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public License along with 00017 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00018 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00019 http://www.gnu.org/copyleft/lesser.txt. 00020 ----------------------------------------------------------------------------- 00021 */ 00022 00027 // implementation 00028 00029 #include <PyObjectPlus.h> 00030 #include <structmember.h> 00031 00032 #include <KX_GameObject.h> 00033 #include <RAS_MeshObject.h> 00034 #include <DNA_mesh_types.h> 00035 #include <DNA_meshdata_types.h> 00036 #include <DNA_image_types.h> 00037 #include <IMB_imbuf_types.h> 00038 #include <KX_PolygonMaterial.h> 00039 00040 #include <MEM_guardedalloc.h> 00041 00042 #include <KX_BlenderMaterial.h> 00043 #include <BL_Texture.h> 00044 00045 #include "KX_KetsjiEngine.h" 00046 #include "KX_PythonInit.h" 00047 #include "Texture.h" 00048 #include "ImageBase.h" 00049 #include "Exception.h" 00050 00051 #include <memory.h> 00052 #include "GL/glew.h" 00053 00054 00055 // macro for exception handling and logging 00056 #define CATCH_EXCP catch (Exception & exp) \ 00057 { exp.report(); return NULL; } 00058 00059 00060 // Blender GameObject type 00061 BlendType<KX_GameObject> gameObjectType ("KX_GameObject"); 00062 00063 00064 // load texture 00065 void loadTexture (unsigned int texId, unsigned int * texture, short * size, 00066 bool mipmap) 00067 { 00068 // load texture for rendering 00069 glBindTexture(GL_TEXTURE_2D, texId); 00070 if (mipmap) 00071 { 00072 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 00073 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00074 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, texture); 00075 } 00076 else 00077 { 00078 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00079 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00080 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size[0], size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); 00081 } 00082 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 00083 } 00084 00085 00086 // get pointer to material 00087 RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID) 00088 { 00089 // if object is available 00090 if (obj != NULL) 00091 { 00092 // get pointer to texture image 00093 KX_GameObject * gameObj = gameObjectType.checkType(obj); 00094 if (gameObj != NULL && gameObj->GetMeshCount() > 0) 00095 { 00096 // get material from mesh 00097 RAS_MeshObject * mesh = gameObj->GetMesh(0); 00098 RAS_MeshMaterial *meshMat = mesh->GetMeshMaterial(matID); 00099 if (meshMat != NULL && meshMat->m_bucket != NULL) 00100 // return pointer to polygon or blender material 00101 return meshMat->m_bucket->GetPolyMaterial(); 00102 } 00103 } 00104 // otherwise material was not found 00105 return NULL; 00106 } 00107 00108 00109 // get material ID 00110 short getMaterialID(PyObject * obj, const char *name) 00111 { 00112 // search for material 00113 for (short matID = 0;; ++matID) 00114 { 00115 // get material 00116 RAS_IPolyMaterial * mat = getMaterial(obj, matID); 00117 // if material is not available, report that no material was found 00118 if (mat == NULL) 00119 break; 00120 // name is a material name if it starts with MA and a UV texture name if it starts with IM 00121 if (name[0] == 'I' && name[1] == 'M') 00122 { 00123 // if texture name matches 00124 if (strcmp(mat->GetTextureName().ReadPtr(), name) == 0) 00125 return matID; 00126 } else 00127 { 00128 // if material name matches 00129 if (strcmp(mat->GetMaterialName().ReadPtr(), name) == 0) 00130 return matID; 00131 } 00132 } 00133 // material was not found 00134 return -1; 00135 } 00136 00137 00138 // Texture object allocation 00139 PyObject * Texture_new (PyTypeObject *type, PyObject *args, PyObject *kwds) 00140 { 00141 // allocate object 00142 Texture * self = reinterpret_cast<Texture*>(type->tp_alloc(type, 0)); 00143 // initialize object structure 00144 self->m_actTex = 0; 00145 self->m_orgSaved = false; 00146 self->m_imgTexture = NULL; 00147 self->m_matTexture = NULL; 00148 self->m_mipmap = false; 00149 self->m_scaledImg = NULL; 00150 self->m_scaledImgSize = 0; 00151 self->m_source = NULL; 00152 self->m_lastClock = 0.0; 00153 // return allocated object 00154 return reinterpret_cast<PyObject*>(self); 00155 } 00156 00157 00158 // forward declaration 00159 PyObject * Texture_close(Texture * self); 00160 int Texture_setSource (Texture * self, PyObject * value, void * closure); 00161 00162 00163 // Texture object deallocation 00164 void Texture_dealloc (Texture * self) 00165 { 00166 // release renderer 00167 Py_XDECREF(self->m_source); 00168 // close texture 00169 PyObject* ret = Texture_close(self); 00170 Py_DECREF(ret); 00171 // release scaled image buffer 00172 delete [] self->m_scaledImg; 00173 // release object 00174 Py_TYPE((PyObject *)self)->tp_free((PyObject*)self); 00175 } 00176 00177 00178 ExceptionID MaterialNotAvail; 00179 ExpDesc MaterialNotAvailDesc (MaterialNotAvail, "Texture material is not available"); 00180 00181 // Texture object initialization 00182 int Texture_init (Texture *self, PyObject *args, PyObject *kwds) 00183 { 00184 // parameters - game object with video texture 00185 PyObject * obj = NULL; 00186 // material ID 00187 short matID = 0; 00188 // texture ID 00189 short texID = 0; 00190 // texture object with shared texture ID 00191 Texture * texObj = NULL; 00192 00193 static const char *kwlist[] = {"gameObj", "materialID", "textureID", "textureObj", NULL}; 00194 00195 // get parameters 00196 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|hhO!", 00197 const_cast<char**>(kwlist), &obj, &matID, &texID, &TextureType, 00198 &texObj)) 00199 return -1; 00200 00201 // if parameters are available 00202 if (obj != NULL) 00203 { 00204 // process polygon material or blender material 00205 try 00206 { 00207 // get pointer to texture image 00208 RAS_IPolyMaterial * mat = getMaterial(obj, matID); 00209 if (mat != NULL) 00210 { 00211 // is it blender material or polygon material 00212 if (mat->GetFlag() & RAS_BLENDERGLSL) 00213 { 00214 self->m_imgTexture = static_cast<KX_BlenderMaterial*>(mat)->getImage(texID); 00215 self->m_useMatTexture = false; 00216 } else if (mat->GetFlag() & RAS_BLENDERMAT) 00217 { 00218 // get blender material texture 00219 self->m_matTexture = static_cast<KX_BlenderMaterial*>(mat)->getTex(texID); 00220 self->m_useMatTexture = true; 00221 } 00222 else 00223 { 00224 // get texture pointer from polygon material 00225 MTFace * tface = static_cast<KX_PolygonMaterial*>(mat)->GetMTFace(); 00226 self->m_imgTexture = (Image*)tface->tpage; 00227 self->m_useMatTexture = false; 00228 } 00229 } 00230 // check if texture is available, if not, initialization failed 00231 if (self->m_imgTexture == NULL && self->m_matTexture == NULL) 00232 // throw exception if initialization failed 00233 THRWEXCP(MaterialNotAvail, S_OK); 00234 00235 // if texture object is provided 00236 if (texObj != NULL) 00237 { 00238 // copy texture code 00239 self->m_actTex = texObj->m_actTex; 00240 self->m_mipmap = texObj->m_mipmap; 00241 if (texObj->m_source != NULL) 00242 Texture_setSource(self, reinterpret_cast<PyObject*>(texObj->m_source), NULL); 00243 } 00244 else 00245 // otherwise generate texture code 00246 glGenTextures(1, (GLuint*)&self->m_actTex); 00247 } 00248 catch (Exception & exp) 00249 { 00250 exp.report(); 00251 return -1; 00252 } 00253 } 00254 // initialization succeded 00255 return 0; 00256 } 00257 00258 00259 // close added texture 00260 PyObject * Texture_close(Texture * self) 00261 { 00262 // restore texture 00263 if (self->m_orgSaved) 00264 { 00265 self->m_orgSaved = false; 00266 // restore original texture code 00267 if (self->m_useMatTexture) 00268 self->m_matTexture->swapTexture(self->m_orgTex); 00269 else 00270 self->m_imgTexture->bindcode = self->m_orgTex; 00271 // drop actual texture 00272 if (self->m_actTex != 0) 00273 { 00274 glDeleteTextures(1, (GLuint *)&self->m_actTex); 00275 self->m_actTex = 0; 00276 } 00277 } 00278 Py_RETURN_NONE; 00279 } 00280 00281 00282 // refresh texture 00283 PyObject * Texture_refresh (Texture * self, PyObject * args) 00284 { 00285 // get parameter - refresh source 00286 PyObject * param; 00287 double ts = -1.0; 00288 00289 if (!PyArg_ParseTuple(args, "O|d:refresh", ¶m, &ts) || !PyBool_Check(param)) 00290 { 00291 // report error 00292 PyErr_SetString(PyExc_TypeError, "The value must be a bool"); 00293 return NULL; 00294 } 00295 // some trick here: we are in the business of loading a texture, 00296 // no use to do it if we are still in the same rendering frame. 00297 // We find this out by looking at the engine current clock time 00298 KX_KetsjiEngine* engine = KX_GetActiveEngine(); 00299 if (engine->GetClockTime() != self->m_lastClock) 00300 { 00301 self->m_lastClock = engine->GetClockTime(); 00302 // set source refresh 00303 bool refreshSource = (param == Py_True); 00304 // try to proces texture from source 00305 try 00306 { 00307 // if source is available 00308 if (self->m_source != NULL) 00309 { 00310 // check texture code 00311 if (!self->m_orgSaved) 00312 { 00313 self->m_orgSaved = true; 00314 // save original image code 00315 if (self->m_useMatTexture) 00316 self->m_orgTex = self->m_matTexture->swapTexture(self->m_actTex); 00317 else 00318 { 00319 self->m_orgTex = self->m_imgTexture->bindcode; 00320 self->m_imgTexture->bindcode = self->m_actTex; 00321 } 00322 } 00323 00324 // get texture 00325 unsigned int * texture = self->m_source->m_image->getImage(self->m_actTex, ts); 00326 // if texture is available 00327 if (texture != NULL) 00328 { 00329 // get texture size 00330 short * orgSize = self->m_source->m_image->getSize(); 00331 // calc scaled sizes 00332 short size[2]; 00333 if (GLEW_ARB_texture_non_power_of_two) 00334 { 00335 size[0] = orgSize[0]; 00336 size[1] = orgSize[1]; 00337 } 00338 else 00339 { 00340 size[0] = ImageBase::calcSize(orgSize[0]); 00341 size[1] = ImageBase::calcSize(orgSize[1]); 00342 } 00343 // scale texture if needed 00344 if (size[0] != orgSize[0] || size[1] != orgSize[1]) 00345 { 00346 // if scaled image buffer is smaller than needed 00347 if (self->m_scaledImgSize < (unsigned int)(size[0] * size[1])) 00348 { 00349 // new size 00350 self->m_scaledImgSize = size[0] * size[1]; 00351 // allocate scaling image 00352 delete [] self->m_scaledImg; 00353 self->m_scaledImg = new unsigned int[self->m_scaledImgSize]; 00354 } 00355 // scale texture 00356 gluScaleImage(GL_RGBA, orgSize[0], orgSize[1], GL_UNSIGNED_BYTE, texture, 00357 size[0], size[1], GL_UNSIGNED_BYTE, self->m_scaledImg); 00358 // use scaled image instead original 00359 texture = self->m_scaledImg; 00360 } 00361 // load texture for rendering 00362 loadTexture (self->m_actTex, texture, size, self->m_mipmap); 00363 00364 // refresh texture source, if required 00365 if (refreshSource) self->m_source->m_image->refresh(); 00366 } 00367 } 00368 } 00369 CATCH_EXCP; 00370 } 00371 Py_RETURN_NONE; 00372 } 00373 00374 // get OpenGL Bind Id 00375 PyObject * Texture_getBindId (Texture * self, void * closure) 00376 { 00377 unsigned int id = self->m_actTex; 00378 return Py_BuildValue("h", id); 00379 } 00380 00381 // get mipmap value 00382 PyObject * Texture_getMipmap (Texture * self, void * closure) 00383 { 00384 // return true if flag is set, otherwise false 00385 if (self->m_mipmap) Py_RETURN_TRUE; 00386 else Py_RETURN_FALSE; 00387 } 00388 00389 // set mipmap value 00390 int Texture_setMipmap (Texture * self, PyObject * value, void * closure) 00391 { 00392 // check parameter, report failure 00393 if (value == NULL || !PyBool_Check(value)) 00394 { 00395 PyErr_SetString(PyExc_TypeError, "The value must be a bool"); 00396 return -1; 00397 } 00398 // set mipmap 00399 self->m_mipmap = value == Py_True; 00400 // success 00401 return 0; 00402 } 00403 00404 00405 // get source object 00406 PyObject * Texture_getSource (Texture * self, PyObject * value, void * closure) 00407 { 00408 // if source exists 00409 if (self->m_source != NULL) 00410 { 00411 Py_INCREF(self->m_source); 00412 return reinterpret_cast<PyObject*>(self->m_source); 00413 } 00414 // otherwise return None 00415 Py_RETURN_NONE; 00416 } 00417 00418 00419 // set source object 00420 int Texture_setSource (Texture * self, PyObject * value, void * closure) 00421 { 00422 // check new value 00423 if (value == NULL || !pyImageTypes.in(Py_TYPE(value))) 00424 { 00425 // report value error 00426 PyErr_SetString(PyExc_TypeError, "Invalid type of value"); 00427 return -1; 00428 } 00429 // increase ref count for new value 00430 Py_INCREF(value); 00431 // release previous 00432 Py_XDECREF(self->m_source); 00433 // set new value 00434 self->m_source = reinterpret_cast<PyImage*>(value); 00435 // return success 00436 return 0; 00437 } 00438 00439 00440 // class Texture methods 00441 static PyMethodDef textureMethods[] = 00442 { 00443 { "close", (PyCFunction)Texture_close, METH_NOARGS, "Close dynamic texture and restore original"}, 00444 { "refresh", (PyCFunction)Texture_refresh, METH_VARARGS, "Refresh texture from source"}, 00445 {NULL} /* Sentinel */ 00446 }; 00447 00448 // class Texture attributes 00449 static PyGetSetDef textureGetSets[] = 00450 { 00451 {(char*)"source", (getter)Texture_getSource, (setter)Texture_setSource, (char*)"source of texture", NULL}, 00452 {(char*)"mipmap", (getter)Texture_getMipmap, (setter)Texture_setMipmap, (char*)"mipmap texture", NULL}, 00453 {(char*)"bindId", (getter)Texture_getBindId, NULL, (char*)"OpenGL Bind Name", NULL}, 00454 {NULL} 00455 }; 00456 00457 00458 // class Texture declaration 00459 PyTypeObject TextureType = 00460 { 00461 PyVarObject_HEAD_INIT(NULL, 0) 00462 "VideoTexture.Texture", /*tp_name*/ 00463 sizeof(Texture), /*tp_basicsize*/ 00464 0, /*tp_itemsize*/ 00465 (destructor)Texture_dealloc,/*tp_dealloc*/ 00466 0, /*tp_print*/ 00467 0, /*tp_getattr*/ 00468 0, /*tp_setattr*/ 00469 0, /*tp_compare*/ 00470 0, /*tp_repr*/ 00471 0, /*tp_as_number*/ 00472 0, /*tp_as_sequence*/ 00473 0, /*tp_as_mapping*/ 00474 0, /*tp_hash */ 00475 0, /*tp_call*/ 00476 0, /*tp_str*/ 00477 0, /*tp_getattro*/ 00478 0, /*tp_setattro*/ 00479 &imageBufferProcs, /*tp_as_buffer*/ 00480 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 00481 "Texture objects", /* tp_doc */ 00482 0, /* tp_traverse */ 00483 0, /* tp_clear */ 00484 0, /* tp_richcompare */ 00485 0, /* tp_weaklistoffset */ 00486 0, /* tp_iter */ 00487 0, /* tp_iternext */ 00488 textureMethods, /* tp_methods */ 00489 0, /* tp_members */ 00490 textureGetSets, /* tp_getset */ 00491 0, /* tp_base */ 00492 0, /* tp_dict */ 00493 0, /* tp_descr_get */ 00494 0, /* tp_descr_set */ 00495 0, /* tp_dictoffset */ 00496 (initproc)Texture_init, /* tp_init */ 00497 0, /* tp_alloc */ 00498 Texture_new, /* tp_new */ 00499 };