|
Blender
V2.59
|
00001 /* 00002 * $Id: GPC_RenderTools.cpp 35170 2011-02-25 13:35:11Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include "GL/glew.h" 00036 00037 #include "RAS_IRenderTools.h" 00038 #include "RAS_IRasterizer.h" 00039 #include "RAS_LightObject.h" 00040 #include "RAS_ICanvas.h" 00041 #include "RAS_GLExtensionManager.h" 00042 00043 #include "KX_GameObject.h" 00044 #include "KX_PolygonMaterial.h" 00045 #include "KX_BlenderMaterial.h" 00046 #include "KX_RayCast.h" 00047 #include "KX_IPhysicsController.h" 00048 #include "KX_Light.h" 00049 00050 #include "PHY_IPhysicsEnvironment.h" 00051 00052 #include "STR_String.h" 00053 00054 #include "GPU_draw.h" 00055 00056 #include "BKE_bmfont.h" // for text printing 00057 #include "BKE_bmfont_types.h" 00058 00059 #include "GPC_RenderTools.h" 00060 00061 extern "C" { 00062 #include "BLF_api.h" 00063 } 00064 00065 00066 unsigned int GPC_RenderTools::m_numgllights; 00067 00068 GPC_RenderTools::GPC_RenderTools() 00069 { 00070 // XXX m_font = BMF_GetFont(BMF_kHelvetica10); 00071 00072 glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights); 00073 if (m_numgllights < 8) 00074 m_numgllights = 8; 00075 } 00076 00077 GPC_RenderTools::~GPC_RenderTools() 00078 { 00079 } 00080 00081 void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) 00082 { 00083 m_clientobject = NULL; 00084 m_lastlightlayer = -1; 00085 m_lastauxinfo = NULL; 00086 m_lastlighting = true; /* force disable in DisableOpenGLLights() */ 00087 DisableOpenGLLights(); 00088 } 00089 00090 void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty) 00091 { 00092 } 00093 00094 /* ProcessLighting performs lighting on objects. the layer is a bitfield that 00095 * contains layer information. There are 20 'official' layers in blender. A 00096 * light is applied on an object only when they are in the same layer. OpenGL 00097 * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in 00098 * a scene. */ 00099 00100 void GPC_RenderTools::ProcessLighting(RAS_IRasterizer *rasty, bool uselights, const MT_Transform& viewmat) 00101 { 00102 bool enable = false; 00103 int layer= -1; 00104 00105 /* find the layer */ 00106 if(uselights) { 00107 if(m_clientobject) 00108 layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer(); 00109 } 00110 00111 /* avoid state switching */ 00112 if(m_lastlightlayer == layer && m_lastauxinfo == m_auxilaryClientInfo) 00113 return; 00114 00115 m_lastlightlayer = layer; 00116 m_lastauxinfo = m_auxilaryClientInfo; 00117 00118 /* enable/disable lights as needed */ 00119 if(layer >= 0) 00120 enable = applyLights(layer, viewmat); 00121 00122 if(enable) 00123 EnableOpenGLLights(rasty); 00124 else 00125 DisableOpenGLLights(); 00126 } 00127 00128 void GPC_RenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty) 00129 { 00130 if(m_lastlighting == true) 00131 return; 00132 00133 glEnable(GL_LIGHTING); 00134 glEnable(GL_COLOR_MATERIAL); 00135 00136 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); 00137 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 00138 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE); 00139 if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) 00140 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); 00141 00142 m_lastlighting = true; 00143 } 00144 00145 void GPC_RenderTools::DisableOpenGLLights() 00146 { 00147 if(m_lastlighting == false) 00148 return; 00149 00150 glDisable(GL_LIGHTING); 00151 glDisable(GL_COLOR_MATERIAL); 00152 00153 m_lastlighting = false; 00154 } 00155 00156 00157 void GPC_RenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) 00158 { 00159 if (m_clientobject != obj) 00160 { 00161 bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); 00162 rasty->SetFrontFace(ccw); 00163 00164 m_clientobject = obj; 00165 } 00166 } 00167 00168 bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) 00169 { 00170 double* const oglmatrix = (double* const) data; 00171 MT_Point3 resultpoint(result->m_hitPoint); 00172 MT_Vector3 resultnormal(result->m_hitNormal); 00173 MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); 00174 MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); 00175 left = (dir.cross(resultnormal)).safe_normalized(); 00176 // for the up vector, we take the 'resultnormal' returned by the physics 00177 00178 double maat[16]={ 00179 left[0], left[1], left[2], 0, 00180 dir[0], dir[1], dir[2], 0, 00181 resultnormal[0],resultnormal[1],resultnormal[2], 0, 00182 0, 0, 0, 1}; 00183 glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); 00184 //glMultMatrixd(oglmatrix); 00185 glMultMatrixd(maat); 00186 return true; 00187 } 00188 00189 void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) 00190 { 00191 /* FIXME: 00192 blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const 00193 MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed. 00194 00195 Program received signal SIGABRT, Aborted. 00196 [Switching to Thread 16384 (LWP 1519)] 00197 0x40477571 in kill () from /lib/libc.so.6 00198 (gdb) bt 00199 #7 0x08334368 in MT_Vector3::normalized() const () 00200 #8 0x0833e6ec in GPC_RenderTools::applyTransform(RAS_IRasterizer*, double*, int) () 00201 */ 00202 00203 if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || 00204 objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) 00205 { 00206 // rotate the billboard/halo 00207 //page 360/361 3D Game Engine Design, David Eberly for a discussion 00208 // on screen aligned and axis aligned billboards 00209 // assumed is that the preprocessor transformed all billboard polygons 00210 // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) 00211 // when new parenting for objects is done, this rotation 00212 // will be moved into the object 00213 00214 MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); 00215 MT_Point3 campos = rasty->GetCameraPosition(); 00216 MT_Vector3 dir = (campos - objpos).safe_normalized(); 00217 MT_Vector3 up(0,0,1.0); 00218 00219 KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; 00220 // get scaling of halo object 00221 MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); 00222 00223 bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned 00224 if (screenaligned) 00225 { 00226 up = (up - up.dot(dir) * dir).safe_normalized(); 00227 } else 00228 { 00229 dir = (dir - up.dot(dir)*up).safe_normalized(); 00230 } 00231 00232 MT_Vector3 left = dir.normalized(); 00233 dir = (left.cross(up)).normalized(); 00234 00235 // we have calculated the row vectors, now we keep 00236 // local scaling into account: 00237 00238 left *= size[0]; 00239 dir *= size[1]; 00240 up *= size[2]; 00241 double maat[16]={ 00242 left[0], left[1],left[2], 0, 00243 dir[0], dir[1],dir[2],0, 00244 up[0],up[1],up[2],0, 00245 0,0,0,1}; 00246 glTranslated(objpos[0],objpos[1],objpos[2]); 00247 glMultMatrixd(maat); 00248 00249 } else 00250 { 00251 if (objectdrawmode & RAS_IPolyMaterial::SHADOW) 00252 { 00253 // shadow must be cast to the ground, physics system needed here! 00254 MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); 00255 KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; 00256 MT_Vector3 direction = MT_Vector3(0,0,-1); 00257 00258 direction.normalize(); 00259 direction *= 100000; 00260 00261 MT_Point3 topoint = frompoint + direction; 00262 00263 KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; 00264 PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); 00265 KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); 00266 00267 KX_GameObject *parent = gameobj->GetParent(); 00268 if (!physics_controller && parent) 00269 physics_controller = parent->GetPhysicsController(); 00270 if (parent) 00271 parent->Release(); 00272 00273 KX_RayCast::Callback<GPC_RenderTools> callback(this, physics_controller, oglmatrix); 00274 if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) 00275 { 00276 // couldn't find something to cast the shadow on... 00277 glMultMatrixd(oglmatrix); 00278 } 00279 } else 00280 { 00281 00282 // 'normal' object 00283 glMultMatrixd(oglmatrix); 00284 } 00285 } 00286 } 00287 00288 void GPC_RenderTools::RenderText3D( int fontid, 00289 const char* text, 00290 int size, 00291 int dpi, 00292 float* color, 00293 double* mat, 00294 float aspect) 00295 { 00296 /* the actual drawing */ 00297 glColor3fv(color); 00298 00299 /* multiply the text matrix by the object matrix */ 00300 BLF_enable(fontid, BLF_MATRIX|BLF_ASPECT); 00301 BLF_matrix(fontid, mat); 00302 00303 /* aspect is the inverse scale that allows you to increase */ 00304 /* your resolution without sizing the final text size */ 00305 /* the bigger the size, the smaller the aspect */ 00306 BLF_aspect(fontid, aspect, aspect, aspect); 00307 00308 BLF_size(fontid, size, dpi); 00309 BLF_position(fontid, 0, 0, 0); 00310 BLF_draw(fontid, (char *)text, strlen(text)); 00311 00312 BLF_disable(fontid, BLF_MATRIX|BLF_ASPECT); 00313 glEnable(GL_DEPTH_TEST); 00314 } 00315 00316 00317 00318 void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, 00319 const char* text, 00320 int xco, 00321 int yco, 00322 int width, 00323 int height) 00324 { 00325 /* 00326 STR_String tmpstr(text); 00327 char* s = tmpstr.Ptr(); */ 00328 00329 // Save and change OpenGL settings 00330 int texture2D; 00331 glGetIntegerv(GL_TEXTURE_2D, (GLint*)&texture2D); 00332 glDisable(GL_TEXTURE_2D); 00333 int fog; 00334 glGetIntegerv(GL_FOG, (GLint*)&fog); 00335 glDisable(GL_FOG); 00336 00337 int light; 00338 glGetIntegerv(GL_LIGHTING, (GLint*)&light); 00339 glDisable(GL_LIGHTING); 00340 00341 00342 // Set up viewing settings 00343 glMatrixMode(GL_PROJECTION); 00344 glPushMatrix(); 00345 glLoadIdentity(); 00346 glOrtho(0, width, 0, height, -1, 1); 00347 glMatrixMode(GL_MODELVIEW); 00348 glPushMatrix(); 00349 glLoadIdentity(); 00350 00351 // Actual drawing (draw black first if padded) 00352 if (mode == RAS_IRenderTools::RAS_TEXT_PADDED) 00353 { 00354 glColor3ub(0, 0, 0); 00355 BLF_draw_default(xco+1, height-yco-1, 0.f, text, strlen(text)); 00356 } 00357 00358 glColor3ub(255, 255, 255); 00359 BLF_draw_default(xco, height-yco, 0.f, text, strlen(text)); 00360 00361 // Restore view settings 00362 glMatrixMode(GL_PROJECTION); 00363 glPopMatrix(); 00364 glMatrixMode(GL_MODELVIEW); 00365 glPopMatrix(); 00366 00367 // Restore OpenGL Settings 00368 if (fog) 00369 glEnable(GL_FOG); 00370 else 00371 glDisable(GL_FOG); 00372 00373 if (texture2D) 00374 glEnable(GL_TEXTURE_2D); 00375 else 00376 glDisable(GL_TEXTURE_2D); 00377 if (light) 00378 glEnable(GL_LIGHTING); 00379 else 00380 glDisable(GL_LIGHTING); 00381 } 00382 00383 /* Render Text renders text into a (series of) polygon, using a texture font, 00384 * Each character consists of one polygon (one quad or two triangles) */ 00385 00386 void GPC_RenderTools::RenderText( 00387 int mode, 00388 RAS_IPolyMaterial* polymat, 00389 float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) 00390 { 00391 STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); 00392 00393 const unsigned int flag = polymat->GetFlag(); 00394 struct MTFace* tface = 0; 00395 unsigned int *col = 0; 00396 00397 if(flag & RAS_BLENDERMAT) { 00398 KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(polymat); 00399 tface = bl_mat->GetMTFace(); 00400 col = bl_mat->GetMCol(); 00401 } else { 00402 KX_PolygonMaterial* blenderpoly = static_cast<KX_PolygonMaterial*>(polymat); 00403 tface = blenderpoly->GetMTFace(); 00404 col = blenderpoly->GetMCol(); 00405 } 00406 00407 GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); 00408 } 00409 00410 00411 void GPC_RenderTools::PushMatrix() 00412 { 00413 glPushMatrix(); 00414 } 00415 00416 void GPC_RenderTools::PopMatrix() 00417 { 00418 glPopMatrix(); 00419 } 00420 00421 00422 int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) 00423 { 00424 // taken from blender source, incompatibility between Blender Object / GameObject 00425 KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo; 00426 float glviewmat[16]; 00427 unsigned int count; 00428 std::vector<struct RAS_LightObject*>::iterator lit = m_lights.begin(); 00429 00430 for(count=0; count<m_numgllights; count++) 00431 glDisable((GLenum)(GL_LIGHT0+count)); 00432 00433 viewmat.getValue(glviewmat); 00434 00435 glPushMatrix(); 00436 glLoadMatrixf(glviewmat); 00437 for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) 00438 { 00439 RAS_LightObject* lightdata = (*lit); 00440 KX_LightObject *kxlight = (KX_LightObject*)lightdata->m_light; 00441 00442 if(kxlight->ApplyLight(kxscene, objectlayer, count)) 00443 count++; 00444 } 00445 glPopMatrix(); 00446 00447 return count; 00448 } 00449 00450 void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer) 00451 { 00452 int state = rasterizer->GetMotionBlurState(); 00453 float motionblurvalue; 00454 if(state) 00455 { 00456 motionblurvalue = rasterizer->GetMotionBlurValue(); 00457 if(state==1) 00458 { 00459 //bugfix:load color buffer into accum buffer for the first time(state=1) 00460 glAccum(GL_LOAD, 1.0); 00461 rasterizer->SetMotionBlurState(2); 00462 } 00463 else if(motionblurvalue>=0.0 && motionblurvalue<=1.0) 00464 { 00465 glAccum(GL_MULT, motionblurvalue); 00466 glAccum(GL_ACCUM, 1-motionblurvalue); 00467 glAccum(GL_RETURN, 1.0); 00468 glFlush(); 00469 } 00470 } 00471 } 00472