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