|
Blender
V2.59
|
00001 /* 00002 * $Id: KX_Light.cpp 35171 2011-02-25 13:35:59Z jesterking $ 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 #if defined(WIN32) && !defined(FREE_WINDOWS) 00035 #pragma warning (disable : 4786) 00036 #endif 00037 00038 #include "GL/glew.h" 00039 00040 #include "KX_Light.h" 00041 #include "KX_Camera.h" 00042 #include "RAS_IRasterizer.h" 00043 #include "RAS_IRenderTools.h" 00044 00045 #include "KX_PyMath.h" 00046 00047 #include "DNA_object_types.h" 00048 #include "DNA_scene_types.h" 00049 #include "GPU_material.h" 00050 00051 KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, 00052 class RAS_IRenderTools* rendertools, 00053 const RAS_LightObject& lightobj, 00054 bool glsl) 00055 : KX_GameObject(sgReplicationInfo,callbacks), 00056 m_rendertools(rendertools) 00057 { 00058 m_lightobj = lightobj; 00059 m_lightobj.m_scene = sgReplicationInfo; 00060 m_lightobj.m_light = this; 00061 m_rendertools->AddLight(&m_lightobj); 00062 m_glsl = glsl; 00063 m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene(); 00064 }; 00065 00066 00067 KX_LightObject::~KX_LightObject() 00068 { 00069 GPULamp *lamp; 00070 00071 if((lamp = GetGPULamp())) { 00072 float obmat[4][4] = {{0}}; 00073 GPU_lamp_update(lamp, 0, 0, obmat); 00074 } 00075 00076 m_rendertools->RemoveLight(&m_lightobj); 00077 } 00078 00079 00080 CValue* KX_LightObject::GetReplica() 00081 { 00082 00083 KX_LightObject* replica = new KX_LightObject(*this); 00084 00085 replica->ProcessReplica(); 00086 00087 replica->m_lightobj.m_light = replica; 00088 m_rendertools->AddLight(&replica->m_lightobj); 00089 00090 return replica; 00091 } 00092 00093 bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot) 00094 { 00095 KX_Scene* lightscene = (KX_Scene*)m_lightobj.m_scene; 00096 float vec[4]; 00097 int scenelayer = ~0; 00098 00099 if(kxscene && kxscene->GetBlenderScene()) 00100 scenelayer = kxscene->GetBlenderScene()->lay; 00101 00102 /* only use lights in the same layer as the object */ 00103 if(!(m_lightobj.m_layer & oblayer)) 00104 return false; 00105 /* only use lights in the same scene, and in a visible layer */ 00106 if(kxscene != lightscene || !(m_lightobj.m_layer & scenelayer)) 00107 return false; 00108 00109 // lights don't get their openGL matrix updated, do it now 00110 if(GetSGNode()->IsDirty()) 00111 GetOpenGLMatrix(); 00112 00113 MT_CmMatrix4x4& worldmatrix= *GetOpenGLMatrixPtr(); 00114 00115 vec[0] = worldmatrix(0,3); 00116 vec[1] = worldmatrix(1,3); 00117 vec[2] = worldmatrix(2,3); 00118 vec[3] = 1.0f; 00119 00120 if(m_lightobj.m_type==RAS_LightObject::LIGHT_SUN) { 00121 00122 vec[0] = worldmatrix(0,2); 00123 vec[1] = worldmatrix(1,2); 00124 vec[2] = worldmatrix(2,2); 00125 //vec[0]= base->object->obmat[2][0]; 00126 //vec[1]= base->object->obmat[2][1]; 00127 //vec[2]= base->object->obmat[2][2]; 00128 vec[3]= 0.0; 00129 glLightfv((GLenum)(GL_LIGHT0+slot), GL_POSITION, vec); 00130 } 00131 else { 00132 //vec[3]= 1.0; 00133 glLightfv((GLenum)(GL_LIGHT0+slot), GL_POSITION, vec); 00134 glLightf((GLenum)(GL_LIGHT0+slot), GL_CONSTANT_ATTENUATION, 1.0); 00135 glLightf((GLenum)(GL_LIGHT0+slot), GL_LINEAR_ATTENUATION, m_lightobj.m_att1/m_lightobj.m_distance); 00136 // without this next line it looks backward compatible. 00137 //attennuation still is acceptable 00138 glLightf((GLenum)(GL_LIGHT0+slot), GL_QUADRATIC_ATTENUATION, m_lightobj.m_att2/(m_lightobj.m_distance*m_lightobj.m_distance)); 00139 00140 if(m_lightobj.m_type==RAS_LightObject::LIGHT_SPOT) { 00141 vec[0] = -worldmatrix(0,2); 00142 vec[1] = -worldmatrix(1,2); 00143 vec[2] = -worldmatrix(2,2); 00144 //vec[0]= -base->object->obmat[2][0]; 00145 //vec[1]= -base->object->obmat[2][1]; 00146 //vec[2]= -base->object->obmat[2][2]; 00147 glLightfv((GLenum)(GL_LIGHT0+slot), GL_SPOT_DIRECTION, vec); 00148 glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_CUTOFF, m_lightobj.m_spotsize/2.0); 00149 glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_EXPONENT, 128.0*m_lightobj.m_spotblend); 00150 } 00151 else 00152 glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_CUTOFF, 180.0); 00153 } 00154 00155 if (m_lightobj.m_nodiffuse) { 00156 vec[0] = vec[1] = vec[2] = vec[3] = 0.0; 00157 } 00158 else { 00159 vec[0]= m_lightobj.m_energy*m_lightobj.m_red; 00160 vec[1]= m_lightobj.m_energy*m_lightobj.m_green; 00161 vec[2]= m_lightobj.m_energy*m_lightobj.m_blue; 00162 vec[3]= 1.0; 00163 } 00164 00165 glLightfv((GLenum)(GL_LIGHT0+slot), GL_DIFFUSE, vec); 00166 if(m_lightobj.m_nospecular) 00167 { 00168 vec[0] = vec[1] = vec[2] = vec[3] = 0.0; 00169 } 00170 else if (m_lightobj.m_nodiffuse) { 00171 vec[0]= m_lightobj.m_energy*m_lightobj.m_red; 00172 vec[1]= m_lightobj.m_energy*m_lightobj.m_green; 00173 vec[2]= m_lightobj.m_energy*m_lightobj.m_blue; 00174 vec[3]= 1.0; 00175 } 00176 00177 glLightfv((GLenum)(GL_LIGHT0+slot), GL_SPECULAR, vec); 00178 glEnable((GLenum)(GL_LIGHT0+slot)); 00179 00180 return true; 00181 } 00182 00183 GPULamp *KX_LightObject::GetGPULamp() 00184 { 00185 if(m_glsl) 00186 return GPU_lamp_from_blender(m_blenderscene, GetBlenderObject(), GetBlenderGroupObject()); 00187 else 00188 return NULL; 00189 } 00190 00191 void KX_LightObject::Update() 00192 { 00193 GPULamp *lamp; 00194 00195 if((lamp = GetGPULamp()) != NULL && GetSGNode()) { 00196 float obmat[4][4]; 00197 // lights don't get their openGL matrix updated, do it now 00198 if (GetSGNode()->IsDirty()) 00199 GetOpenGLMatrix(); 00200 double *dobmat = GetOpenGLMatrixPtr()->getPointer(); 00201 00202 for(int i=0; i<4; i++) 00203 for(int j=0; j<4; j++, dobmat++) 00204 obmat[i][j] = (float)*dobmat; 00205 00206 GPU_lamp_update(lamp, m_lightobj.m_layer, 0, obmat); 00207 GPU_lamp_update_colors(lamp, m_lightobj.m_red, m_lightobj.m_green, 00208 m_lightobj.m_blue, m_lightobj.m_energy); 00209 } 00210 } 00211 00212 bool KX_LightObject::HasShadowBuffer() 00213 { 00214 GPULamp *lamp; 00215 00216 if((lamp = GetGPULamp())) 00217 return GPU_lamp_has_shadow_buffer(lamp); 00218 else 00219 return false; 00220 } 00221 00222 int KX_LightObject::GetShadowLayer() 00223 { 00224 GPULamp *lamp; 00225 00226 if((lamp = GetGPULamp())) 00227 return GPU_lamp_shadow_layer(lamp); 00228 else 00229 return 0; 00230 } 00231 00232 void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans) 00233 { 00234 GPULamp *lamp; 00235 float viewmat[4][4], winmat[4][4]; 00236 int winsize; 00237 00238 /* bind framebuffer */ 00239 lamp = GetGPULamp(); 00240 GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat); 00241 00242 /* setup camera transformation */ 00243 MT_Matrix4x4 modelviewmat((float*)viewmat); 00244 MT_Matrix4x4 projectionmat((float*)winmat); 00245 00246 MT_Transform trans = MT_Transform((float*)viewmat); 00247 camtrans.invert(trans); 00248 00249 cam->SetModelviewMatrix(modelviewmat); 00250 cam->SetProjectionMatrix(projectionmat); 00251 00252 cam->NodeSetLocalPosition(camtrans.getOrigin()); 00253 cam->NodeSetLocalOrientation(camtrans.getBasis()); 00254 cam->NodeUpdateGS(0); 00255 00256 /* setup rasterizer transformations */ 00257 ras->SetProjectionMatrix(projectionmat); 00258 ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective); 00259 } 00260 00261 void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) 00262 { 00263 GPULamp *lamp = GetGPULamp(); 00264 GPU_lamp_shadow_buffer_unbind(lamp); 00265 } 00266 00267 #ifdef WITH_PYTHON 00268 /* ------------------------------------------------------------------------- */ 00269 /* Python Integration Hooks */ 00270 /* ------------------------------------------------------------------------- */ 00271 00272 PyTypeObject KX_LightObject::Type = { 00273 PyVarObject_HEAD_INIT(NULL, 0) 00274 "KX_LightObject", 00275 sizeof(PyObjectPlus_Proxy), 00276 0, 00277 py_base_dealloc, 00278 0, 00279 0, 00280 0, 00281 0, 00282 py_base_repr, 00283 0, 00284 &KX_GameObject::Sequence, 00285 &KX_GameObject::Mapping, 00286 0,0,0, 00287 NULL, 00288 NULL, 00289 0, 00290 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00291 0,0,0,0,0,0,0, 00292 Methods, 00293 0, 00294 0, 00295 &KX_GameObject::Type, 00296 0,0,0,0,0,0, 00297 py_base_new 00298 }; 00299 00300 PyMethodDef KX_LightObject::Methods[] = { 00301 {NULL,NULL} //Sentinel 00302 }; 00303 00304 PyAttributeDef KX_LightObject::Attributes[] = { 00305 KX_PYATTRIBUTE_INT_RW("layer", 1, 20, true, KX_LightObject, m_lightobj.m_layer), 00306 KX_PYATTRIBUTE_FLOAT_RW("energy", 0, 10, KX_LightObject, m_lightobj.m_energy), 00307 KX_PYATTRIBUTE_FLOAT_RW("distance", 0.01, 5000, KX_LightObject, m_lightobj.m_distance), 00308 KX_PYATTRIBUTE_RW_FUNCTION("color", KX_LightObject, pyattr_get_color, pyattr_set_color), 00309 KX_PYATTRIBUTE_FLOAT_RW("lin_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att1), 00310 KX_PYATTRIBUTE_FLOAT_RW("quad_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att2), 00311 KX_PYATTRIBUTE_FLOAT_RW("spotsize", 1, 180, KX_LightObject, m_lightobj.m_spotsize), 00312 KX_PYATTRIBUTE_FLOAT_RW("spotblend", 0, 1, KX_LightObject, m_lightobj.m_spotblend), 00313 KX_PYATTRIBUTE_RO_FUNCTION("SPOT", KX_LightObject, pyattr_get_typeconst), 00314 KX_PYATTRIBUTE_RO_FUNCTION("SUN", KX_LightObject, pyattr_get_typeconst), 00315 KX_PYATTRIBUTE_RO_FUNCTION("NORMAL", KX_LightObject, pyattr_get_typeconst), 00316 KX_PYATTRIBUTE_RW_FUNCTION("type", KX_LightObject, pyattr_get_type, pyattr_set_type), 00317 { NULL } //Sentinel 00318 }; 00319 00320 PyObject* KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00321 { 00322 KX_LightObject* self = static_cast<KX_LightObject*>(self_v); 00323 return Py_BuildValue("[fff]", self->m_lightobj.m_red, self->m_lightobj.m_green, self->m_lightobj.m_blue); 00324 } 00325 00326 int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00327 { 00328 KX_LightObject* self = static_cast<KX_LightObject*>(self_v); 00329 00330 MT_Vector3 color; 00331 if (PyVecTo(value, color)) 00332 { 00333 self->m_lightobj.m_red = color[0]; 00334 self->m_lightobj.m_green = color[1]; 00335 self->m_lightobj.m_blue = color[2]; 00336 return PY_SET_ATTR_SUCCESS; 00337 } 00338 return PY_SET_ATTR_FAIL; 00339 } 00340 00341 PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00342 { 00343 PyObject* retvalue; 00344 00345 const char* type = attrdef->m_name; 00346 00347 if(!strcmp(type, "SPOT")) { 00348 retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SPOT); 00349 } else if (!strcmp(type, "SUN")) { 00350 retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SUN); 00351 } else if (!strcmp(type, "NORMAL")) { 00352 retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_NORMAL); 00353 } 00354 else { 00355 /* should never happen */ 00356 PyErr_SetString(PyExc_TypeError, "light.type: internal error, invalid light type"); 00357 retvalue = NULL; 00358 } 00359 00360 return retvalue; 00361 } 00362 00363 PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00364 { 00365 KX_LightObject* self = static_cast<KX_LightObject*>(self_v); 00366 return PyLong_FromSsize_t(self->m_lightobj.m_type); 00367 } 00368 00369 int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value) 00370 { 00371 KX_LightObject* self = static_cast<KX_LightObject*>(self_v); 00372 int val = PyLong_AsSsize_t(value); 00373 if((val==-1 && PyErr_Occurred()) || val<0 || val>2) { 00374 PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2"); 00375 return PY_SET_ATTR_FAIL; 00376 } 00377 00378 switch(val) { 00379 case 0: 00380 self->m_lightobj.m_type = self->m_lightobj.LIGHT_SPOT; 00381 break; 00382 case 1: 00383 self->m_lightobj.m_type = self->m_lightobj.LIGHT_SUN; 00384 break; 00385 case 2: 00386 self->m_lightobj.m_type = self->m_lightobj.LIGHT_NORMAL; 00387 break; 00388 } 00389 00390 return PY_SET_ATTR_SUCCESS; 00391 } 00392 #endif // WITH_PYTHON