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 #include "GL/glew.h" 00034 00035 #include "RAS_IRenderTools.h" 00036 #include "RAS_IRasterizer.h" 00037 #include "RAS_LightObject.h" 00038 #include "RAS_ICanvas.h" 00039 #include "RAS_GLExtensionManager.h" 00040 00041 #include "KX_GameObject.h" 00042 #include "KX_PolygonMaterial.h" 00043 #include "KX_BlenderMaterial.h" 00044 #include "KX_RayCast.h" 00045 #include "KX_IPhysicsController.h" 00046 #include "KX_Light.h" 00047 00048 #include "PHY_IPhysicsEnvironment.h" 00049 00050 #include "STR_String.h" 00051 00052 #include "GPU_draw.h" 00053 00054 #include "KX_BlenderGL.h" // for text printing 00055 #include "KX_BlenderRenderTools.h" 00056 00057 unsigned int KX_BlenderRenderTools::m_numgllights; 00058 00059 KX_BlenderRenderTools::KX_BlenderRenderTools() 00060 { 00061 glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights); 00062 if (m_numgllights < 8) 00063 m_numgllights = 8; 00064 } 00065 00066 KX_BlenderRenderTools::~KX_BlenderRenderTools() 00067 { 00068 } 00069 00070 void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty) 00071 { 00072 m_clientobject = NULL; 00073 m_lastlightlayer = -1; 00074 m_lastauxinfo = NULL; 00075 m_lastlighting = true; /* force disable in DisableOpenGLLights() */ 00076 DisableOpenGLLights(); 00077 } 00078 00079 void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) 00080 { 00081 } 00082 00083 /* ProcessLighting performs lighting on objects. the layer is a bitfield that 00084 * contains layer information. There are 20 'official' layers in blender. A 00085 * light is applied on an object only when they are in the same layer. OpenGL 00086 * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in 00087 * a scene. */ 00088 00089 void KX_BlenderRenderTools::ProcessLighting(RAS_IRasterizer *rasty, bool uselights, const MT_Transform& viewmat) 00090 { 00091 bool enable = false; 00092 int layer= -1; 00093 00094 /* find the layer */ 00095 if(uselights) { 00096 if(m_clientobject) 00097 layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer(); 00098 } 00099 00100 /* avoid state switching */ 00101 if(m_lastlightlayer == layer && m_lastauxinfo == m_auxilaryClientInfo) 00102 return; 00103 00104 m_lastlightlayer = layer; 00105 m_lastauxinfo = m_auxilaryClientInfo; 00106 00107 /* enable/disable lights as needed */ 00108 if(layer >= 0) 00109 enable = applyLights(layer, viewmat); 00110 00111 if(enable) 00112 EnableOpenGLLights(rasty); 00113 else 00114 DisableOpenGLLights(); 00115 } 00116 00117 void KX_BlenderRenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty) 00118 { 00119 if(m_lastlighting == true) 00120 return; 00121 00122 glEnable(GL_LIGHTING); 00123 glEnable(GL_COLOR_MATERIAL); 00124 00125 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); 00126 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 00127 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE); 00128 if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) 00129 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); 00130 00131 m_lastlighting = true; 00132 } 00133 00134 void KX_BlenderRenderTools::DisableOpenGLLights() 00135 { 00136 if(m_lastlighting == false) 00137 return; 00138 00139 glDisable(GL_LIGHTING); 00140 glDisable(GL_COLOR_MATERIAL); 00141 00142 m_lastlighting = false; 00143 } 00144 00145 00146 void KX_BlenderRenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) 00147 { 00148 if (m_clientobject != obj) 00149 { 00150 bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); 00151 rasty->SetFrontFace(ccw); 00152 00153 m_clientobject = obj; 00154 } 00155 } 00156 00157 bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) 00158 { 00159 double* const oglmatrix = (double* const) data; 00160 MT_Point3 resultpoint(result->m_hitPoint); 00161 MT_Vector3 resultnormal(result->m_hitNormal); 00162 MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); 00163 MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); 00164 left = (dir.cross(resultnormal)).safe_normalized(); 00165 // for the up vector, we take the 'resultnormal' returned by the physics 00166 00167 double maat[16]={ 00168 left[0], left[1], left[2], 0, 00169 dir[0], dir[1], dir[2], 0, 00170 resultnormal[0],resultnormal[1],resultnormal[2], 0, 00171 0, 0, 0, 1}; 00172 glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); 00173 //glMultMatrixd(oglmatrix); 00174 glMultMatrixd(maat); 00175 return true; 00176 } 00177 00178 void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) 00179 { 00180 /* FIXME: 00181 blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const 00182 MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed. 00183 00184 Program received signal SIGABRT, Aborted. 00185 [Switching to Thread 16384 (LWP 1519)] 00186 0x40477571 in kill () from /lib/libc.so.6 00187 (gdb) bt 00188 #7 0x08334368 in MT_Vector3::normalized() const () 00189 #8 0x0833e6ec in KX_BlenderRenderTools::applyTransform(RAS_IRasterizer*, double*, int) () 00190 */ 00191 00192 if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || 00193 objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) 00194 { 00195 // rotate the billboard/halo 00196 //page 360/361 3D Game Engine Design, David Eberly for a discussion 00197 // on screen aligned and axis aligned billboards 00198 // assumed is that the preprocessor transformed all billboard polygons 00199 // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) 00200 // when new parenting for objects is done, this rotation 00201 // will be moved into the object 00202 00203 MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); 00204 MT_Point3 campos = rasty->GetCameraPosition(); 00205 MT_Vector3 dir = (campos - objpos).safe_normalized(); 00206 MT_Vector3 up(0,0,1.0); 00207 00208 KX_GameObject* gameobj = (KX_GameObject*)m_clientobject; 00209 // get scaling of halo object 00210 MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); 00211 00212 bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned 00213 if (screenaligned) 00214 { 00215 up = (up - up.dot(dir) * dir).safe_normalized(); 00216 } else 00217 { 00218 dir = (dir - up.dot(dir)*up).safe_normalized(); 00219 } 00220 00221 MT_Vector3 left = dir.normalized(); 00222 dir = (left.cross(up)).normalized(); 00223 00224 // we have calculated the row vectors, now we keep 00225 // local scaling into account: 00226 00227 left *= size[0]; 00228 dir *= size[1]; 00229 up *= size[2]; 00230 double maat[16]={ 00231 left[0], left[1],left[2], 0, 00232 dir[0], dir[1],dir[2],0, 00233 up[0],up[1],up[2],0, 00234 0,0,0,1}; 00235 glTranslated(objpos[0],objpos[1],objpos[2]); 00236 glMultMatrixd(maat); 00237 00238 } else 00239 { 00240 if (objectdrawmode & RAS_IPolyMaterial::SHADOW) 00241 { 00242 // shadow must be cast to the ground, physics system needed here! 00243 MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); 00244 KX_GameObject *gameobj = (KX_GameObject*)m_clientobject; 00245 MT_Vector3 direction = MT_Vector3(0,0,-1); 00246 00247 direction.normalize(); 00248 direction *= 100000; 00249 00250 MT_Point3 topoint = frompoint + direction; 00251 00252 KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; 00253 PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); 00254 KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); 00255 00256 KX_GameObject *parent = gameobj->GetParent(); 00257 if (!physics_controller && parent) 00258 physics_controller = parent->GetPhysicsController(); 00259 if (parent) 00260 parent->Release(); 00261 00262 KX_RayCast::Callback<KX_BlenderRenderTools> callback(this, physics_controller, oglmatrix); 00263 if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) 00264 { 00265 // couldn't find something to cast the shadow on... 00266 glMultMatrixd(oglmatrix); 00267 } 00268 else 00269 { // we found the "ground", but the cast matrix doesn't take 00270 // scaling in consideration, so we must apply the object scale 00271 MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); 00272 glScalef(size[0], size[1], size[2]); 00273 } 00274 } else 00275 { 00276 00277 // 'normal' object 00278 glMultMatrixd(oglmatrix); 00279 } 00280 } 00281 } 00282 void KX_BlenderRenderTools::RenderText3D(int fontid, 00283 const char* text, 00284 int size, 00285 int dpi, 00286 float* color, 00287 double* mat, 00288 float aspect) 00289 { 00290 BL_print_game_line(fontid, text, size, dpi, color, mat, aspect); 00291 } 00292 00293 void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, 00294 const char* text, 00295 int xco, 00296 int yco, 00297 int width, 00298 int height) 00299 { 00300 if(mode == RAS_IRenderTools::RAS_TEXT_PADDED) 00301 BL_print_gamedebug_line_padded(text, xco, yco, width, height); 00302 else 00303 BL_print_gamedebug_line(text, xco, yco, width, height); 00304 } 00305 00306 /* Render Text renders text into a (series of) polygon, using a texture font, 00307 * Each character consists of one polygon (one quad or two triangles) */ 00308 00309 void KX_BlenderRenderTools::RenderText( 00310 int mode, 00311 RAS_IPolyMaterial* polymat, 00312 float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) 00313 { 00314 const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); 00315 00316 const unsigned int flag = polymat->GetFlag(); 00317 struct MTFace* tface = 0; 00318 unsigned int *col = 0; 00319 00320 if(flag & RAS_BLENDERMAT) { 00321 KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(polymat); 00322 tface = bl_mat->GetMTFace(); 00323 col = bl_mat->GetMCol(); 00324 } else { 00325 KX_PolygonMaterial* blenderpoly = static_cast<KX_PolygonMaterial*>(polymat); 00326 tface = blenderpoly->GetMTFace(); 00327 col = blenderpoly->GetMCol(); 00328 } 00329 00330 GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); 00331 } 00332 00333 00334 void KX_BlenderRenderTools::PushMatrix() 00335 { 00336 glPushMatrix(); 00337 } 00338 00339 void KX_BlenderRenderTools::PopMatrix() 00340 { 00341 glPopMatrix(); 00342 } 00343 00344 00345 int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) 00346 { 00347 // taken from blender source, incompatibility between Blender Object / GameObject 00348 KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo; 00349 float glviewmat[16]; 00350 unsigned int count; 00351 std::vector<struct RAS_LightObject*>::iterator lit = m_lights.begin(); 00352 00353 for(count=0; count<m_numgllights; count++) 00354 glDisable((GLenum)(GL_LIGHT0+count)); 00355 00356 viewmat.getValue(glviewmat); 00357 00358 glPushMatrix(); 00359 glLoadMatrixf(glviewmat); 00360 for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) 00361 { 00362 RAS_LightObject* lightdata = (*lit); 00363 KX_LightObject *kxlight = (KX_LightObject*)lightdata->m_light; 00364 00365 if(kxlight->ApplyLight(kxscene, objectlayer, count)) 00366 count++; 00367 } 00368 glPopMatrix(); 00369 00370 return count; 00371 } 00372 00373 void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer) 00374 { 00375 int state = rasterizer->GetMotionBlurState(); 00376 float motionblurvalue; 00377 if(state) 00378 { 00379 motionblurvalue = rasterizer->GetMotionBlurValue(); 00380 if(state==1) 00381 { 00382 //bugfix:load color buffer into accum buffer for the first time(state=1) 00383 glAccum(GL_LOAD, 1.0); 00384 rasterizer->SetMotionBlurState(2); 00385 } 00386 else if(motionblurvalue>=0.0 && motionblurvalue<=1.0) 00387 { 00388 glAccum(GL_MULT, motionblurvalue); 00389 glAccum(GL_ACCUM, 1-motionblurvalue); 00390 glAccum(GL_RETURN, 1.0); 00391 glFlush(); 00392 } 00393 } 00394 }