|
Blender
V2.59
|
00001 /* 00002 * $Id: RAS_OpenGLRasterizer.cpp 36470 2011-05-04 01:50:17Z dfelinto $ 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 #include <math.h> 00035 #include <stdlib.h> 00036 00037 #include "RAS_OpenGLRasterizer.h" 00038 00039 #include "GL/glew.h" 00040 00041 #include "RAS_Rect.h" 00042 #include "RAS_TexVert.h" 00043 #include "RAS_MeshObject.h" 00044 #include "MT_CmMatrix4x4.h" 00045 #include "RAS_IRenderTools.h" // rendering text 00046 00047 #include "GPU_draw.h" 00048 #include "GPU_material.h" 00049 #include "GPU_extensions.h" 00050 00051 #include "DNA_image_types.h" 00052 #include "DNA_meshdata_types.h" 00053 #include "DNA_material_types.h" 00054 #include "DNA_scene_types.h" 00055 00056 #include "BKE_DerivedMesh.h" 00057 00061 static GLuint left_eye_vinterlace_mask[32]; 00062 static GLuint right_eye_vinterlace_mask[32]; 00063 00069 static GLuint hinterlace_mask[33]; 00070 00071 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) 00072 :RAS_IRasterizer(canvas), 00073 m_2DCanvas(canvas), 00074 m_fogenabled(false), 00075 m_time(0.0), 00076 m_campos(0.0f, 0.0f, 0.0f), 00077 m_camortho(false), 00078 m_stereomode(RAS_STEREO_NOSTEREO), 00079 m_curreye(RAS_STEREO_LEFTEYE), 00080 m_eyeseparation(0.0), 00081 m_focallength(0.0), 00082 m_setfocallength(false), 00083 m_noOfScanlines(32), 00084 m_motionblur(0), 00085 m_motionblurvalue(-1.0), 00086 m_texco_num(0), 00087 m_attrib_num(0), 00088 //m_last_blendmode(GPU_BLEND_SOLID), 00089 m_last_frontface(true), 00090 m_materialCachingInfo(0) 00091 { 00092 m_viewmatrix.setIdentity(); 00093 m_viewinvmatrix.setIdentity(); 00094 00095 for (int i = 0; i < 32; i++) 00096 { 00097 left_eye_vinterlace_mask[i] = 0x55555555; 00098 right_eye_vinterlace_mask[i] = 0xAAAAAAAA; 00099 hinterlace_mask[i] = (i&1)*0xFFFFFFFF; 00100 } 00101 hinterlace_mask[32] = 0; 00102 } 00103 00104 00105 00106 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() 00107 { 00108 } 00109 00110 bool RAS_OpenGLRasterizer::Init() 00111 { 00112 GPU_state_init(); 00113 00114 00115 m_ambr = 0.0f; 00116 m_ambg = 0.0f; 00117 m_ambb = 0.0f; 00118 00119 glDisable(GL_BLEND); 00120 glDisable(GL_ALPHA_TEST); 00121 //m_last_blendmode = GPU_BLEND_SOLID; 00122 GPU_set_material_blend_mode(GPU_BLEND_SOLID); 00123 00124 glFrontFace(GL_CCW); 00125 m_last_frontface = true; 00126 00127 m_redback = 0.4375; 00128 m_greenback = 0.4375; 00129 m_blueback = 0.4375; 00130 m_alphaback = 0.0; 00131 00132 glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); 00133 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 00134 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00135 00136 00137 glShadeModel(GL_SMOOTH); 00138 00139 return true; 00140 } 00141 00142 00143 void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) 00144 { 00145 m_ambr = red; 00146 m_ambg = green; 00147 m_ambb = blue; 00148 } 00149 00150 00151 void RAS_OpenGLRasterizer::SetAmbient(float factor) 00152 { 00153 float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; 00154 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); 00155 } 00156 00157 00158 void RAS_OpenGLRasterizer::SetBackColor(float red, 00159 float green, 00160 float blue, 00161 float alpha) 00162 { 00163 m_redback = red; 00164 m_greenback = green; 00165 m_blueback = blue; 00166 m_alphaback = alpha; 00167 } 00168 00169 00170 00171 void RAS_OpenGLRasterizer::SetFogColor(float r, 00172 float g, 00173 float b) 00174 { 00175 m_fogr = r; 00176 m_fogg = g; 00177 m_fogb = b; 00178 m_fogenabled = true; 00179 } 00180 00181 00182 00183 void RAS_OpenGLRasterizer::SetFogStart(float start) 00184 { 00185 m_fogstart = start; 00186 m_fogenabled = true; 00187 } 00188 00189 00190 00191 void RAS_OpenGLRasterizer::SetFogEnd(float fogend) 00192 { 00193 m_fogdist = fogend; 00194 m_fogenabled = true; 00195 } 00196 00197 00198 00199 void RAS_OpenGLRasterizer::SetFog(float start, 00200 float dist, 00201 float r, 00202 float g, 00203 float b) 00204 { 00205 m_fogstart = start; 00206 m_fogdist = dist; 00207 m_fogr = r; 00208 m_fogg = g; 00209 m_fogb = b; 00210 m_fogenabled = true; 00211 } 00212 00213 00214 00215 void RAS_OpenGLRasterizer::DisableFog() 00216 { 00217 m_fogenabled = false; 00218 } 00219 00220 bool RAS_OpenGLRasterizer::IsFogEnabled() 00221 { 00222 return m_fogenabled; 00223 } 00224 00225 00226 void RAS_OpenGLRasterizer::DisplayFog() 00227 { 00228 if ((m_drawingmode >= KX_SOLID) && m_fogenabled) 00229 { 00230 float params[5]; 00231 glFogi(GL_FOG_MODE, GL_LINEAR); 00232 glFogf(GL_FOG_DENSITY, 0.1f); 00233 glFogf(GL_FOG_START, m_fogstart); 00234 glFogf(GL_FOG_END, m_fogstart + m_fogdist); 00235 params[0]= m_fogr; 00236 params[1]= m_fogg; 00237 params[2]= m_fogb; 00238 params[3]= 0.0; 00239 glFogfv(GL_FOG_COLOR, params); 00240 glEnable(GL_FOG); 00241 } 00242 else 00243 { 00244 glDisable(GL_FOG); 00245 } 00246 } 00247 00248 00249 00250 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat) 00251 { 00252 return mat.Activate(this, m_materialCachingInfo); 00253 } 00254 00255 00256 00257 void RAS_OpenGLRasterizer::Exit() 00258 { 00259 00260 glEnable(GL_CULL_FACE); 00261 glEnable(GL_DEPTH_TEST); 00262 glClearDepth(1.0); 00263 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 00264 glClearColor(m_redback, m_greenback, m_blueback, m_alphaback); 00265 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00266 glDepthMask (GL_TRUE); 00267 glDepthFunc(GL_LEQUAL); 00268 glBlendFunc(GL_ONE, GL_ZERO); 00269 00270 glDisable(GL_POLYGON_STIPPLE); 00271 00272 glDisable(GL_LIGHTING); 00273 if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) 00274 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 00275 00276 EndFrame(); 00277 } 00278 00279 bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) 00280 { 00281 m_time = time; 00282 m_drawingmode = drawingmode; 00283 00284 // Blender camera routine destroys the settings 00285 if (m_drawingmode < KX_SOLID) 00286 { 00287 glDisable (GL_CULL_FACE); 00288 glDisable (GL_DEPTH_TEST); 00289 } 00290 else 00291 { 00292 glEnable(GL_DEPTH_TEST); 00293 glEnable (GL_CULL_FACE); 00294 } 00295 00296 glDisable(GL_BLEND); 00297 glDisable(GL_ALPHA_TEST); 00298 //m_last_blendmode = GPU_BLEND_SOLID; 00299 GPU_set_material_blend_mode(GPU_BLEND_SOLID); 00300 00301 glFrontFace(GL_CCW); 00302 m_last_frontface = true; 00303 00304 glShadeModel(GL_SMOOTH); 00305 00306 glEnable(GL_MULTISAMPLE_ARB); 00307 00308 m_2DCanvas->BeginFrame(); 00309 00310 return true; 00311 } 00312 00313 00314 00315 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) 00316 { 00317 m_drawingmode = drawingmode; 00318 00319 if(m_drawingmode == KX_WIREFRAME) 00320 glDisable(GL_CULL_FACE); 00321 } 00322 00323 int RAS_OpenGLRasterizer::GetDrawingMode() 00324 { 00325 return m_drawingmode; 00326 } 00327 00328 00329 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask) 00330 { 00331 glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE); 00332 } 00333 00334 00335 void RAS_OpenGLRasterizer::ClearColorBuffer() 00336 { 00337 m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); 00338 m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); 00339 } 00340 00341 00342 void RAS_OpenGLRasterizer::ClearDepthBuffer() 00343 { 00344 m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER); 00345 } 00346 00347 00348 void RAS_OpenGLRasterizer::ClearCachingInfo(void) 00349 { 00350 m_materialCachingInfo = 0; 00351 } 00352 00353 void RAS_OpenGLRasterizer::FlushDebugLines() 00354 { 00355 if(!m_debugLines.size()) 00356 return; 00357 00358 // DrawDebugLines 00359 GLboolean light, tex; 00360 00361 light= glIsEnabled(GL_LIGHTING); 00362 tex= glIsEnabled(GL_TEXTURE_2D); 00363 00364 if(light) glDisable(GL_LIGHTING); 00365 if(tex) glDisable(GL_TEXTURE_2D); 00366 00367 glBegin(GL_LINES); 00368 for (unsigned int i=0;i<m_debugLines.size();i++) 00369 { 00370 glColor4f(m_debugLines[i].m_color[0],m_debugLines[i].m_color[1],m_debugLines[i].m_color[2],1.f); 00371 const MT_Scalar* fromPtr = &m_debugLines[i].m_from.x(); 00372 const MT_Scalar* toPtr= &m_debugLines[i].m_to.x(); 00373 00374 glVertex3dv(fromPtr); 00375 glVertex3dv(toPtr); 00376 } 00377 glEnd(); 00378 00379 if(light) glEnable(GL_LIGHTING); 00380 if(tex) glEnable(GL_TEXTURE_2D); 00381 00382 m_debugLines.clear(); 00383 } 00384 00385 void RAS_OpenGLRasterizer::EndFrame() 00386 { 00387 00388 00389 FlushDebugLines(); 00390 00391 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 00392 00393 glDisable(GL_MULTISAMPLE_ARB); 00394 00395 m_2DCanvas->EndFrame(); 00396 } 00397 00398 void RAS_OpenGLRasterizer::SetRenderArea() 00399 { 00400 RAS_Rect area; 00401 // only above/below stereo method needs viewport adjustment 00402 switch (m_stereomode) 00403 { 00404 case RAS_STEREO_ABOVEBELOW: 00405 switch(m_curreye) 00406 { 00407 case RAS_STEREO_LEFTEYE: 00408 // upper half of window 00409 area.SetLeft(0); 00410 area.SetBottom(m_2DCanvas->GetHeight() - 00411 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2); 00412 00413 area.SetRight(int(m_2DCanvas->GetWidth())); 00414 area.SetTop(int(m_2DCanvas->GetHeight())); 00415 m_2DCanvas->SetDisplayArea(&area); 00416 break; 00417 case RAS_STEREO_RIGHTEYE: 00418 // lower half of window 00419 area.SetLeft(0); 00420 area.SetBottom(0); 00421 area.SetRight(int(m_2DCanvas->GetWidth())); 00422 area.SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2); 00423 m_2DCanvas->SetDisplayArea(&area); 00424 break; 00425 } 00426 break; 00427 case RAS_STEREO_SIDEBYSIDE: 00428 switch (m_curreye) 00429 { 00430 case RAS_STEREO_LEFTEYE: 00431 // Left half of window 00432 area.SetLeft(0); 00433 area.SetBottom(0); 00434 area.SetRight(m_2DCanvas->GetWidth()/2); 00435 area.SetTop(m_2DCanvas->GetHeight()); 00436 m_2DCanvas->SetDisplayArea(&area); 00437 break; 00438 case RAS_STEREO_RIGHTEYE: 00439 // Right half of window 00440 area.SetLeft(m_2DCanvas->GetWidth()/2); 00441 area.SetBottom(0); 00442 area.SetRight(m_2DCanvas->GetWidth()); 00443 area.SetTop(m_2DCanvas->GetHeight()); 00444 m_2DCanvas->SetDisplayArea(&area); 00445 break; 00446 } 00447 break; 00448 default: 00449 // every available pixel 00450 area.SetLeft(0); 00451 area.SetBottom(0); 00452 area.SetRight(int(m_2DCanvas->GetWidth())); 00453 area.SetTop(int(m_2DCanvas->GetHeight())); 00454 m_2DCanvas->SetDisplayArea(&area); 00455 break; 00456 } 00457 } 00458 00459 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode) 00460 { 00461 m_stereomode = stereomode; 00462 } 00463 00464 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode() 00465 { 00466 return m_stereomode; 00467 } 00468 00469 bool RAS_OpenGLRasterizer::Stereo() 00470 { 00471 if(m_stereomode > RAS_STEREO_NOSTEREO) // > 0 00472 return true; 00473 else 00474 return false; 00475 } 00476 00477 bool RAS_OpenGLRasterizer::InterlacedStereo() 00478 { 00479 return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; 00480 } 00481 00482 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye) 00483 { 00484 m_curreye = eye; 00485 switch (m_stereomode) 00486 { 00487 case RAS_STEREO_QUADBUFFERED: 00488 glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT); 00489 break; 00490 case RAS_STEREO_ANAGLYPH: 00491 if (m_curreye == RAS_STEREO_LEFTEYE) 00492 { 00493 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE); 00494 } else { 00495 //glAccum(GL_LOAD, 1.0); 00496 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); 00497 ClearDepthBuffer(); 00498 } 00499 break; 00500 case RAS_STEREO_VINTERLACE: 00501 { 00502 glEnable(GL_POLYGON_STIPPLE); 00503 glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask)); 00504 if (m_curreye == RAS_STEREO_RIGHTEYE) 00505 ClearDepthBuffer(); 00506 break; 00507 } 00508 case RAS_STEREO_INTERLACED: 00509 { 00510 glEnable(GL_POLYGON_STIPPLE); 00511 glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]); 00512 if (m_curreye == RAS_STEREO_RIGHTEYE) 00513 ClearDepthBuffer(); 00514 break; 00515 } 00516 default: 00517 break; 00518 } 00519 } 00520 00521 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye() 00522 { 00523 return m_curreye; 00524 } 00525 00526 00527 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation) 00528 { 00529 m_eyeseparation = eyeseparation; 00530 } 00531 00532 float RAS_OpenGLRasterizer::GetEyeSeparation() 00533 { 00534 return m_eyeseparation; 00535 } 00536 00537 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength) 00538 { 00539 m_focallength = focallength; 00540 m_setfocallength = true; 00541 } 00542 00543 float RAS_OpenGLRasterizer::GetFocalLength() 00544 { 00545 return m_focallength; 00546 } 00547 00548 00549 void RAS_OpenGLRasterizer::SwapBuffers() 00550 { 00551 m_2DCanvas->SwapBuffers(); 00552 } 00553 00554 00555 00556 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const 00557 { 00558 return m_viewmatrix; 00559 } 00560 00561 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const 00562 { 00563 return m_viewinvmatrix; 00564 } 00565 00566 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, 00567 class RAS_IPolyMaterial* polymat, 00568 class RAS_IRenderTools* rendertools) 00569 { 00570 bool obcolor = ms.m_bObjectColor; 00571 MT_Vector4& rgba = ms.m_RGBAcolor; 00572 RAS_MeshSlot::iterator it; 00573 00574 // handle object color 00575 if (obcolor) { 00576 glDisableClientState(GL_COLOR_ARRAY); 00577 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); 00578 } 00579 else 00580 glEnableClientState(GL_COLOR_ARRAY); 00581 00582 for(ms.begin(it); !ms.end(it); ms.next(it)) { 00583 RAS_TexVert *vertex; 00584 size_t i, j, numvert; 00585 00586 numvert = it.array->m_type; 00587 00588 if(it.array->m_type == RAS_DisplayArray::LINE) { 00589 // line drawing, no text 00590 glBegin(GL_LINES); 00591 00592 for(i=0; i<it.totindex; i+=2) 00593 { 00594 vertex = &it.vertex[it.index[i]]; 00595 glVertex3fv(vertex->getXYZ()); 00596 00597 vertex = &it.vertex[it.index[i+1]]; 00598 glVertex3fv(vertex->getXYZ()); 00599 } 00600 00601 glEnd(); 00602 } 00603 else { 00604 // triangle and quad text drawing 00605 for(i=0; i<it.totindex; i+=numvert) 00606 { 00607 float v[4][3]; 00608 int glattrib, unit; 00609 00610 for(j=0; j<numvert; j++) { 00611 vertex = &it.vertex[it.index[i+j]]; 00612 00613 v[j][0] = vertex->getXYZ()[0]; 00614 v[j][1] = vertex->getXYZ()[1]; 00615 v[j][2] = vertex->getXYZ()[2]; 00616 } 00617 00618 // find the right opengl attribute 00619 glattrib = -1; 00620 if(GLEW_ARB_vertex_program) 00621 for(unit=0; unit<m_attrib_num; unit++) 00622 if(m_attrib[unit] == RAS_TEXCO_UV1) 00623 glattrib = unit; 00624 00625 rendertools->RenderText(polymat->GetDrawingMode(), polymat, 00626 v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib); 00627 00628 ClearCachingInfo(); 00629 } 00630 } 00631 } 00632 00633 glDisableClientState(GL_COLOR_ARRAY); 00634 } 00635 00636 void RAS_OpenGLRasterizer::SetTexCoordNum(int num) 00637 { 00638 m_texco_num = num; 00639 if(m_texco_num > RAS_MAX_TEXCO) 00640 m_texco_num = RAS_MAX_TEXCO; 00641 } 00642 00643 void RAS_OpenGLRasterizer::SetAttribNum(int num) 00644 { 00645 m_attrib_num = num; 00646 if(m_attrib_num > RAS_MAX_ATTRIB) 00647 m_attrib_num = RAS_MAX_ATTRIB; 00648 } 00649 00650 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit) 00651 { 00652 // this changes from material to material 00653 if(unit < RAS_MAX_TEXCO) 00654 m_texco[unit] = coords; 00655 } 00656 00657 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit) 00658 { 00659 // this changes from material to material 00660 if(unit < RAS_MAX_ATTRIB) 00661 m_attrib[unit] = coords; 00662 } 00663 00664 void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv) 00665 { 00666 int unit; 00667 00668 if(GLEW_ARB_multitexture) { 00669 for(unit=0; unit<m_texco_num; unit++) { 00670 if(tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) { 00671 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); 00672 continue; 00673 } 00674 switch(m_texco[unit]) { 00675 case RAS_TEXCO_ORCO: 00676 case RAS_TEXCO_GLOB: 00677 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ()); 00678 break; 00679 case RAS_TEXCO_UV1: 00680 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1()); 00681 break; 00682 case RAS_TEXCO_NORM: 00683 glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal()); 00684 break; 00685 case RAS_TEXTANGENT: 00686 glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent()); 00687 break; 00688 case RAS_TEXCO_UV2: 00689 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); 00690 break; 00691 default: 00692 break; 00693 } 00694 } 00695 } 00696 00697 if(GLEW_ARB_vertex_program) { 00698 for(unit=0; unit<m_attrib_num; unit++) { 00699 switch(m_attrib[unit]) { 00700 case RAS_TEXCO_ORCO: 00701 case RAS_TEXCO_GLOB: 00702 glVertexAttrib3fvARB(unit, tv.getXYZ()); 00703 break; 00704 case RAS_TEXCO_UV1: 00705 glVertexAttrib2fvARB(unit, tv.getUV1()); 00706 break; 00707 case RAS_TEXCO_NORM: 00708 glVertexAttrib3fvARB(unit, tv.getNormal()); 00709 break; 00710 case RAS_TEXTANGENT: 00711 glVertexAttrib4fvARB(unit, tv.getTangent()); 00712 break; 00713 case RAS_TEXCO_UV2: 00714 glVertexAttrib2fvARB(unit, tv.getUV2()); 00715 break; 00716 case RAS_TEXCO_VCOL: 00717 glVertexAttrib4ubvARB(unit, tv.getRGBA()); 00718 break; 00719 default: 00720 break; 00721 } 00722 } 00723 } 00724 00725 } 00726 00727 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) 00728 { 00729 IndexPrimitivesInternal(ms, false); 00730 } 00731 00732 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) 00733 { 00734 IndexPrimitivesInternal(ms, true); 00735 } 00736 00737 static bool current_wireframe; 00738 static RAS_MaterialBucket *current_bucket; 00739 static RAS_IPolyMaterial *current_polymat; 00740 static RAS_MeshSlot *current_ms; 00741 static RAS_MeshObject *current_mesh; 00742 static int current_blmat_nr; 00743 static GPUVertexAttribs current_gpu_attribs; 00744 static Image *current_image; 00745 static int CheckMaterialDM(int matnr, void *attribs) 00746 { 00747 // only draw the current material 00748 if (matnr != current_blmat_nr) 00749 return 0; 00750 GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs; 00751 if (gattribs) 00752 memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs)); 00753 return 1; 00754 } 00755 00756 /* 00757 static int CheckTexfaceDM(void *mcol, int index) 00758 { 00759 00760 // index is the original face index, retrieve the polygon 00761 RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ? 00762 current_mesh->GetPolygon(index) : NULL; 00763 if (polygon && polygon->GetMaterial() == current_bucket) { 00764 // must handle color. 00765 if (current_wireframe) 00766 return 2; 00767 if (current_ms->m_bObjectColor) { 00768 MT_Vector4& rgba = current_ms->m_RGBAcolor; 00769 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); 00770 // don't use mcol 00771 return 2; 00772 } 00773 if (!mcol) { 00774 // we have to set the color from the material 00775 unsigned char rgba[4]; 00776 current_polymat->GetMaterialRGBAColor(rgba); 00777 glColor4ubv((const GLubyte *)rgba); 00778 return 2; 00779 } 00780 return 1; 00781 } 00782 return 0; 00783 } 00784 */ 00785 00786 static int CheckTexDM(MTFace *tface, MCol *mcol, int matnr) 00787 { 00788 00789 // index is the original face index, retrieve the polygon 00790 if (matnr == current_blmat_nr && 00791 (tface == NULL || tface->tpage == current_image)) { 00792 // must handle color. 00793 if (current_wireframe) 00794 return 2; 00795 if (current_ms->m_bObjectColor) { 00796 MT_Vector4& rgba = current_ms->m_RGBAcolor; 00797 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); 00798 // don't use mcol 00799 return 2; 00800 } 00801 if (!mcol) { 00802 // we have to set the color from the material 00803 unsigned char rgba[4]; 00804 current_polymat->GetMaterialRGBAColor(rgba); 00805 glColor4ubv((const GLubyte *)rgba); 00806 return 2; 00807 } 00808 return 1; 00809 } 00810 return 0; 00811 } 00812 00813 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) 00814 { 00815 bool obcolor = ms.m_bObjectColor; 00816 bool wireframe = m_drawingmode <= KX_WIREFRAME; 00817 MT_Vector4& rgba = ms.m_RGBAcolor; 00818 RAS_MeshSlot::iterator it; 00819 00820 if (ms.m_pDerivedMesh) { 00821 // mesh data is in derived mesh, 00822 current_bucket = ms.m_bucket; 00823 current_polymat = current_bucket->GetPolyMaterial(); 00824 current_ms = &ms; 00825 current_mesh = ms.m_mesh; 00826 current_wireframe = wireframe; 00827 // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */ 00828 00829 // handle two-side 00830 if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_TWOSIDE) 00831 this->SetCullFace(false); 00832 else 00833 this->SetCullFace(true); 00834 00835 if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { 00836 // GetMaterialIndex return the original mface material index, 00837 // increment by 1 to match what derived mesh is doing 00838 current_blmat_nr = current_polymat->GetMaterialIndex()+1; 00839 // For GLSL we need to retrieve the GPU material attribute 00840 Material* blmat = current_polymat->GetBlenderMaterial(); 00841 Scene* blscene = current_polymat->GetBlenderScene(); 00842 if (!wireframe && blscene && blmat) 00843 GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), ¤t_gpu_attribs); 00844 else 00845 memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); 00846 // DM draw can mess up blending mode, restore at the end 00847 int current_blend_mode = GPU_get_material_blend_mode(); 00848 ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM); 00849 GPU_set_material_blend_mode(current_blend_mode); 00850 } else { 00851 //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol); 00852 current_blmat_nr = current_polymat->GetMaterialIndex(); 00853 current_image = current_polymat->GetBlenderImage(); 00854 ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM); 00855 } 00856 return; 00857 } 00858 // iterate over display arrays, each containing an index + vertex array 00859 for(ms.begin(it); !ms.end(it); ms.next(it)) { 00860 RAS_TexVert *vertex; 00861 size_t i, j, numvert; 00862 00863 numvert = it.array->m_type; 00864 00865 if(it.array->m_type == RAS_DisplayArray::LINE) { 00866 // line drawing 00867 glBegin(GL_LINES); 00868 00869 for(i=0; i<it.totindex; i+=2) 00870 { 00871 vertex = &it.vertex[it.index[i]]; 00872 glVertex3fv(vertex->getXYZ()); 00873 00874 vertex = &it.vertex[it.index[i+1]]; 00875 glVertex3fv(vertex->getXYZ()); 00876 } 00877 00878 glEnd(); 00879 } 00880 else { 00881 // triangle and quad drawing 00882 if(it.array->m_type == RAS_DisplayArray::TRIANGLE) 00883 glBegin(GL_TRIANGLES); 00884 else 00885 glBegin(GL_QUADS); 00886 00887 for(i=0; i<it.totindex; i+=numvert) 00888 { 00889 if(obcolor) 00890 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); 00891 00892 for(j=0; j<numvert; j++) { 00893 vertex = &it.vertex[it.index[i+j]]; 00894 00895 if(!wireframe) { 00896 if(!obcolor) 00897 glColor4ubv((const GLubyte *)(vertex->getRGBA())); 00898 00899 glNormal3fv(vertex->getNormal()); 00900 00901 if(multi) 00902 TexCoord(*vertex); 00903 else 00904 glTexCoord2fv(vertex->getUV1()); 00905 } 00906 00907 glVertex3fv(vertex->getXYZ()); 00908 } 00909 } 00910 00911 glEnd(); 00912 } 00913 } 00914 } 00915 00916 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) 00917 { 00918 glMatrixMode(GL_PROJECTION); 00919 double* matrix = &mat(0,0); 00920 glLoadMatrixd(matrix); 00921 00922 m_camortho= (mat(3, 3) != 0.0f); 00923 } 00924 00925 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) 00926 { 00927 glMatrixMode(GL_PROJECTION); 00928 double matrix[16]; 00929 /* Get into argument. Looks a bit dodgy, but it's ok. */ 00930 mat.getValue(matrix); 00931 /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */ 00932 glLoadMatrixd(matrix); 00933 00934 m_camortho= (mat[3][3] != 0.0f); 00935 } 00936 00937 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( 00938 float left, 00939 float right, 00940 float bottom, 00941 float top, 00942 float frustnear, 00943 float frustfar, 00944 float focallength, 00945 bool 00946 ){ 00947 MT_Matrix4x4 result; 00948 double mat[16]; 00949 00950 // correction for stereo 00951 if(Stereo()) 00952 { 00953 float near_div_focallength; 00954 float offset; 00955 00956 // if Rasterizer.setFocalLength is not called we use the camera focallength 00957 if (!m_setfocallength) 00958 // if focallength is null we use a value known to be reasonable 00959 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0 00960 : focallength; 00961 00962 near_div_focallength = frustnear / m_focallength; 00963 offset = 0.5 * m_eyeseparation * near_div_focallength; 00964 switch(m_curreye) 00965 { 00966 case RAS_STEREO_LEFTEYE: 00967 left += offset; 00968 right += offset; 00969 break; 00970 case RAS_STEREO_RIGHTEYE: 00971 left -= offset; 00972 right -= offset; 00973 break; 00974 } 00975 // leave bottom and top untouched 00976 } 00977 00978 glMatrixMode(GL_PROJECTION); 00979 glLoadIdentity(); 00980 glFrustum(left, right, bottom, top, frustnear, frustfar); 00981 00982 glGetDoublev(GL_PROJECTION_MATRIX, mat); 00983 result.setValue(mat); 00984 00985 return result; 00986 } 00987 00988 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix( 00989 float left, 00990 float right, 00991 float bottom, 00992 float top, 00993 float frustnear, 00994 float frustfar 00995 ){ 00996 MT_Matrix4x4 result; 00997 double mat[16]; 00998 00999 // stereo is meaning less for orthographic, disable it 01000 glMatrixMode(GL_PROJECTION); 01001 glLoadIdentity(); 01002 glOrtho(left, right, bottom, top, frustnear, frustfar); 01003 01004 glGetDoublev(GL_PROJECTION_MATRIX, mat); 01005 result.setValue(mat); 01006 01007 return result; 01008 } 01009 01010 01011 // next arguments probably contain redundant info, for later... 01012 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, 01013 const MT_Matrix3x3 & camOrientMat3x3, 01014 const MT_Point3 & pos, 01015 bool perspective) 01016 { 01017 m_viewmatrix = mat; 01018 01019 // correction for stereo 01020 if(Stereo() && perspective) 01021 { 01022 MT_Vector3 unitViewDir(0.0, -1.0, 0.0); // minus y direction, Blender convention 01023 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0); 01024 MT_Vector3 viewDir, viewupVec; 01025 MT_Vector3 eyeline; 01026 01027 // actual viewDir 01028 viewDir = camOrientMat3x3 * unitViewDir; // this is the moto convention, vector on right hand side 01029 // actual viewup vec 01030 viewupVec = camOrientMat3x3 * unitViewupVec; 01031 01032 // vector between eyes 01033 eyeline = viewDir.cross(viewupVec); 01034 01035 switch(m_curreye) 01036 { 01037 case RAS_STEREO_LEFTEYE: 01038 { 01039 // translate to left by half the eye distance 01040 MT_Transform transform; 01041 transform.setIdentity(); 01042 transform.translate(-(eyeline * m_eyeseparation / 2.0)); 01043 m_viewmatrix *= transform; 01044 } 01045 break; 01046 case RAS_STEREO_RIGHTEYE: 01047 { 01048 // translate to right by half the eye distance 01049 MT_Transform transform; 01050 transform.setIdentity(); 01051 transform.translate(eyeline * m_eyeseparation / 2.0); 01052 m_viewmatrix *= transform; 01053 } 01054 break; 01055 } 01056 } 01057 01058 m_viewinvmatrix = m_viewmatrix; 01059 m_viewinvmatrix.invert(); 01060 01061 // note: getValue gives back column major as needed by OpenGL 01062 MT_Scalar glviewmat[16]; 01063 m_viewmatrix.getValue(glviewmat); 01064 01065 glMatrixMode(GL_MODELVIEW); 01066 glLoadMatrixd(glviewmat); 01067 m_campos = pos; 01068 } 01069 01070 01071 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition() 01072 { 01073 return m_campos; 01074 } 01075 01076 bool RAS_OpenGLRasterizer::GetCameraOrtho() 01077 { 01078 return m_camortho; 01079 } 01080 01081 void RAS_OpenGLRasterizer::SetCullFace(bool enable) 01082 { 01083 if (enable) 01084 glEnable(GL_CULL_FACE); 01085 else 01086 glDisable(GL_CULL_FACE); 01087 } 01088 01089 void RAS_OpenGLRasterizer::SetLines(bool enable) 01090 { 01091 if (enable) 01092 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 01093 else 01094 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 01095 } 01096 01097 void RAS_OpenGLRasterizer::SetSpecularity(float specX, 01098 float specY, 01099 float specZ, 01100 float specval) 01101 { 01102 GLfloat mat_specular[] = {specX, specY, specZ, specval}; 01103 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); 01104 } 01105 01106 01107 01108 void RAS_OpenGLRasterizer::SetShinyness(float shiny) 01109 { 01110 GLfloat mat_shininess[] = { shiny }; 01111 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); 01112 } 01113 01114 01115 01116 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse) 01117 { 01118 GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse}; 01119 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); 01120 } 01121 01122 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e) 01123 { 01124 GLfloat mat_emit [] = {eX,eY,eZ,e}; 01125 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit); 01126 } 01127 01128 01129 double RAS_OpenGLRasterizer::GetTime() 01130 { 01131 return m_time; 01132 } 01133 01134 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add) 01135 { 01136 glPolygonOffset(mult, add); 01137 GLint mode = GL_POLYGON_OFFSET_FILL; 01138 if (m_drawingmode < KX_SHADED) 01139 mode = GL_POLYGON_OFFSET_LINE; 01140 if (mult != 0.0f || add != 0.0f) 01141 glEnable(mode); 01142 else 01143 glDisable(mode); 01144 } 01145 01146 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue) 01147 { 01148 /* don't just set m_motionblur to 1, but check if it is 0 so 01149 * we don't reset a motion blur that is already enabled */ 01150 if(m_motionblur == 0) 01151 m_motionblur = 1; 01152 m_motionblurvalue = motionblurvalue; 01153 } 01154 01155 void RAS_OpenGLRasterizer::DisableMotionBlur() 01156 { 01157 m_motionblur = 0; 01158 m_motionblurvalue = -1.0; 01159 } 01160 01161 void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) 01162 { 01163 GPU_set_material_blend_mode(blendmode); 01164 /* 01165 if(blendmode == m_last_blendmode) 01166 return; 01167 01168 if(blendmode == GPU_BLEND_SOLID) { 01169 glDisable(GL_BLEND); 01170 glDisable(GL_ALPHA_TEST); 01171 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 01172 } 01173 else if(blendmode == GPU_BLEND_ADD) { 01174 glBlendFunc(GL_ONE, GL_ONE); 01175 glEnable(GL_BLEND); 01176 glDisable(GL_ALPHA_TEST); 01177 } 01178 else if(blendmode == GPU_BLEND_ALPHA) { 01179 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 01180 glEnable(GL_BLEND); 01181 glEnable(GL_ALPHA_TEST); 01182 glAlphaFunc(GL_GREATER, 0.0f); 01183 } 01184 else if(blendmode == GPU_BLEND_CLIP) { 01185 glDisable(GL_BLEND); 01186 glEnable(GL_ALPHA_TEST); 01187 glAlphaFunc(GL_GREATER, 0.5f); 01188 } 01189 01190 m_last_blendmode = blendmode; 01191 */ 01192 } 01193 01194 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw) 01195 { 01196 if(m_last_frontface == ccw) 01197 return; 01198 01199 if(ccw) 01200 glFrontFace(GL_CCW); 01201 else 01202 glFrontFace(GL_CW); 01203 01204 m_last_frontface = ccw; 01205 } 01206