|
Blender
V2.59
|
00001 00004 /* $Id: KX_Dome.cpp 35171 2011-02-25 13:35:59Z jesterking $ 00005 ----------------------------------------------------------------------------- 00006 00007 This program is free software; you can redistribute it and/or modify it under 00008 the terms of the GNU Lesser General Public License as published by the Free Software 00009 Foundation; either version 2 of the License, or (at your option) any later 00010 version. 00011 00012 This program is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00014 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public License along with 00017 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00018 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00019 http://www.gnu.org/copyleft/lesser.txt. 00020 00021 Contributor(s): Dalai Felinto 00022 00023 This code is originally inspired on some of the ideas and codes from Paul Bourke. 00024 Developed as part of a Research and Development project for SAT - La Société des arts technologiques. 00025 ----------------------------------------------------------------------------- 00026 */ 00027 00028 #include "KX_Dome.h" 00029 00030 #ifdef WITH_PYTHON 00031 #include <structmember.h> 00032 #endif 00033 00034 #include <float.h> 00035 #include <math.h> 00036 00037 #include "DNA_scene_types.h" 00038 #include "RAS_CameraData.h" 00039 #include "BLI_math.h" 00040 00041 #include "GL/glew.h" 00042 00043 // constructor 00044 KX_Dome::KX_Dome ( 00045 RAS_ICanvas* canvas, 00047 RAS_IRasterizer* rasterizer, 00049 RAS_IRenderTools* rendertools, 00051 KX_KetsjiEngine* engine, 00052 00053 short res, //resolution of the mesh 00054 short mode, //mode - fisheye, truncated, warped, panoramic, ... 00055 short angle, 00056 float resbuf, //size adjustment of the buffer 00057 short tilt, 00058 struct Text* warptext 00059 00060 ): 00061 dlistSupported(false), 00062 canvaswidth(-1), canvasheight(-1), 00063 m_drawingmode(engine->GetDrawType()), 00064 m_resolution(res), 00065 m_mode(mode), 00066 m_angle(angle), 00067 m_resbuffer(resbuf), 00068 m_tilt(tilt), 00069 m_canvas(canvas), 00070 m_rasterizer(rasterizer), 00071 m_rendertools(rendertools), 00072 m_engine(engine) 00073 { 00074 warp.usemesh = false; 00075 fboSupported = false; 00076 00077 if (mode >= DOME_NUM_MODES) 00078 m_mode = DOME_FISHEYE; 00079 00080 if (warptext) // it there is a text data try to warp it 00081 { 00082 char *buf; 00083 buf = txt_to_buf(warptext); 00084 if (buf) 00085 { 00086 warp.usemesh = ParseWarpMesh(STR_String(buf)); 00087 MEM_freeN(buf); 00088 } 00089 } 00090 00091 //setting the viewport size 00092 GLuint viewport[4]={0}; 00093 glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); 00094 00095 SetViewPort(viewport); 00096 00097 switch(m_mode){ 00098 case DOME_FISHEYE: 00099 if (m_angle <= 180){ 00100 cubetop.resize(1); 00101 cubebottom.resize(1); 00102 cubeleft.resize(2); 00103 cuberight.resize(2); 00104 00105 CreateMeshDome180(); 00106 m_numfaces = 4; 00107 }else if (m_angle > 180){ 00108 cubetop.resize(2); 00109 cubebottom.resize(2); 00110 cubeleft.resize(2); 00111 cubefront.resize(2); 00112 cuberight.resize(2); 00113 00114 CreateMeshDome250(); 00115 m_numfaces = 5; 00116 } break; 00117 case DOME_ENVMAP: 00118 m_angle = 360; 00119 m_numfaces = 6; 00120 break; 00121 case DOME_PANORAM_SPH: 00122 cubeleft.resize(2); 00123 cubeleftback.resize(2); 00124 cuberight.resize(2); 00125 cuberightback.resize(2); 00126 cubetop.resize(2); 00127 cubebottom.resize(2); 00128 00129 m_angle = 360; 00130 CreateMeshPanorama(); 00131 m_numfaces = 6; 00132 break; 00133 default: //DOME_TRUNCATED_FRONT and DOME_TRUNCATED_REAR 00134 if (m_angle <= 180){ 00135 cubetop.resize(1); 00136 cubebottom.resize(1); 00137 cubeleft.resize(2); 00138 cuberight.resize(2); 00139 00140 CreateMeshDome180(); 00141 m_numfaces = 4; 00142 }else if (m_angle > 180){ 00143 cubetop.resize(2); 00144 cubebottom.resize(2); 00145 cubeleft.resize(2); 00146 cubefront.resize(2); 00147 cuberight.resize(2); 00148 00149 CreateMeshDome250(); 00150 m_numfaces = 5; 00151 } break; 00152 } 00153 00154 m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces); 00155 00156 CalculateCameraOrientation(); 00157 00158 CreateGLImages(); 00159 00160 if(warp.usemesh) 00161 fboSupported = CreateFBO(); 00162 00163 dlistSupported = CreateDL(); 00164 } 00165 00166 // destructor 00167 KX_Dome::~KX_Dome (void) 00168 { 00169 ClearGLImages(); 00170 00171 if(fboSupported) 00172 glDeleteFramebuffersEXT(1, &warp.fboId); 00173 00174 if(dlistSupported) 00175 glDeleteLists(dlistId, (GLsizei) m_numimages); 00176 } 00177 00178 void KX_Dome::SetViewPort(GLuint viewport[4]) 00179 { 00180 if(canvaswidth != m_viewport.GetWidth() || canvasheight != m_viewport.GetHeight()) 00181 { 00182 m_viewport.SetLeft(viewport[0]); 00183 m_viewport.SetBottom(viewport[1]); 00184 m_viewport.SetRight(viewport[2]); 00185 m_viewport.SetTop(viewport[3]); 00186 00187 CalculateImageSize(); 00188 } 00189 } 00190 00191 void KX_Dome::CreateGLImages(void) 00192 { 00193 glGenTextures(m_numimages, (GLuint*)&domefacesId); 00194 00195 for (int j=0;j<m_numfaces;j++){ 00196 glBindTexture(GL_TEXTURE_2D, domefacesId[j]); 00197 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_imagesize, m_imagesize, 0, GL_RGB8, 00198 GL_UNSIGNED_BYTE, 0); 00199 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, m_imagesize, m_imagesize, 0); 00200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 00203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 00204 } 00205 if(warp.usemesh){ 00206 glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); 00207 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagesize, warp.imagesize, 0, GL_RGB8, 00208 GL_UNSIGNED_BYTE, 0); 00209 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagesize, warp.imagesize, 0); 00210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 00213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 00214 } 00215 } 00216 00217 void KX_Dome::ClearGLImages(void) 00218 { 00219 glDeleteTextures(m_numimages, (GLuint*)&domefacesId); 00220 /* 00221 for (int i=0;i<m_numimages;i++) 00222 if(glIsTexture(domefacesId[i])) 00223 glDeleteTextures(1, (GLuint*)&domefacesId[i]); 00224 */ 00225 } 00226 00227 void KX_Dome::CalculateImageSize(void) 00228 { 00229 /* 00230 - determine the minimum buffer size 00231 - reduce the buffer for better performace 00232 - create a power of 2 texture bigger than the buffer 00233 */ 00234 /* 00235 Blender handles Canvas size differently when in fullscreen mode. 00236 We are manually checking for that. Although it's a hack, it works. 00237 00238 Bug reported here: #18655 - Inconsistency of pixels in canvas dimensions when in maximized mode (affecting BGE Dome) 00239 http://projects.blender.org/tracker/?func=detail&aid=18655&group_id=9&atid=125 00240 */ 00241 00242 canvaswidth = m_canvas->GetWidth(); 00243 canvasheight = m_canvas->GetHeight(); 00244 00245 bool fullscreen(false); //XXX HACK 00246 fullscreen = (canvaswidth != m_viewport.GetWidth()); 00247 00248 m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth); 00249 m_buffersize = (int)(m_buffersize*m_resbuffer); //reduce buffer size for better performance 00250 00251 if (fullscreen) //XXX HACK 00252 m_buffersize --; 00253 00254 int i = 0; 00255 while ((1 << i) <= m_buffersize) 00256 i++; 00257 m_imagesize = (1 << i); 00258 00259 if (warp.usemesh){ 00260 // warp FBO needs to be up to twice as big as m_buffersize to get more resolution 00261 warp.imagesize = m_imagesize; 00262 if (m_buffersize == m_imagesize) 00263 warp.imagesize *= 2; 00264 00265 //if FBO is not working/supported, we use the canvas dimension as buffer 00266 warp.bufferwidth = canvaswidth; 00267 warp.bufferheight = canvasheight; 00268 } 00269 00270 //XXX HACK 00271 canvaswidth = m_viewport.GetWidth(); 00272 canvasheight = m_viewport.GetHeight(); 00273 } 00274 00275 bool KX_Dome::CreateDL(){ 00276 dlistId = glGenLists((GLsizei) m_numimages); 00277 if (dlistId != 0) { 00278 if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED_FRONT || m_mode == DOME_TRUNCATED_REAR){ 00279 glNewList(dlistId, GL_COMPILE); 00280 GLDrawTriangles(cubetop, nfacestop); 00281 glEndList(); 00282 00283 glNewList(dlistId+1, GL_COMPILE); 00284 GLDrawTriangles(cubebottom, nfacesbottom); 00285 glEndList(); 00286 00287 glNewList(dlistId+2, GL_COMPILE); 00288 GLDrawTriangles(cubeleft, nfacesleft); 00289 glEndList(); 00290 00291 glNewList(dlistId+3, GL_COMPILE); 00292 GLDrawTriangles(cuberight, nfacesright); 00293 glEndList(); 00294 00295 if (m_angle > 180){ 00296 glNewList(dlistId+4, GL_COMPILE); 00297 GLDrawTriangles(cubefront, nfacesfront); 00298 glEndList(); 00299 } 00300 } 00301 else if (m_mode == DOME_PANORAM_SPH) 00302 { 00303 glNewList(dlistId, GL_COMPILE); 00304 GLDrawTriangles(cubetop, nfacestop); 00305 glEndList(); 00306 00307 glNewList(dlistId+1, GL_COMPILE); 00308 GLDrawTriangles(cubebottom, nfacesbottom); 00309 glEndList(); 00310 00311 glNewList(dlistId+2, GL_COMPILE); 00312 GLDrawTriangles(cubeleft, nfacesleft); 00313 glEndList(); 00314 00315 glNewList(dlistId+3, GL_COMPILE); 00316 GLDrawTriangles(cuberight, nfacesright); 00317 glEndList(); 00318 00319 glNewList(dlistId+4, GL_COMPILE); 00320 GLDrawTriangles(cubeleftback, nfacesleftback); 00321 glEndList(); 00322 00323 glNewList(dlistId+5, GL_COMPILE); 00324 GLDrawTriangles(cuberightback, nfacesrightback); 00325 glEndList(); 00326 } 00327 00328 if(warp.usemesh){ 00329 glNewList((dlistId + m_numfaces), GL_COMPILE); 00330 GLDrawWarpQuads(); 00331 glEndList(); 00332 } 00333 00334 //clearing the vectors 00335 cubetop.clear(); 00336 cubebottom.clear(); 00337 cuberight.clear(); 00338 cubeleft.clear(); 00339 cubefront.clear(); 00340 cubeleftback.clear(); 00341 cuberightback.clear(); 00342 warp.nodes.clear(); 00343 00344 } else // genList failed 00345 return false; 00346 00347 return true; 00348 } 00349 00350 bool KX_Dome::CreateFBO(void) 00351 { 00352 if (!GLEW_EXT_framebuffer_object) 00353 { 00354 printf("Dome Error: FrameBuffer unsupported. Using low resolution warp image."); 00355 return false; 00356 } 00357 00358 glGenFramebuffersEXT(1, &warp.fboId); 00359 if(warp.fboId==0) 00360 { 00361 printf("Dome Error: Invalid frame buffer object. Using low resolution warp image."); 00362 return false; 00363 } 00364 00365 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId); 00366 00367 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 00368 GL_TEXTURE_2D, domefacesId[m_numfaces], 0); 00369 00370 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 00371 00372 if(status == GL_FRAMEBUFFER_UNSUPPORTED_EXT) 00373 { 00374 printf("Dome Error: FrameBuffer settings unsupported. Using low resolution warp image."); 00375 return false; 00376 } 00377 else if(status != GL_FRAMEBUFFER_COMPLETE_EXT) 00378 { 00379 glDeleteFramebuffersEXT(1, &warp.fboId); 00380 return false; 00381 } 00382 00383 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 00384 00385 //nothing failed: we can use the whole FBO as buffersize 00386 warp.bufferwidth = warp.bufferheight = warp.imagesize; 00387 return true; 00388 } 00389 00390 void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces) 00391 { 00392 int i,j; 00393 glBegin(GL_TRIANGLES); 00394 for (i=0;i<nfaces;i++) { 00395 for (j=0;j<3;j++) { 00396 glTexCoord2f(face[i].u[j],face[i].v[j]); 00397 glVertex3f((GLfloat)face[i].verts[j][0],(GLfloat)face[i].verts[j][1],(GLfloat)face[i].verts[j][2]); 00398 } 00399 } 00400 glEnd(); 00401 } 00402 00403 void KX_Dome::GLDrawWarpQuads(void) 00404 { 00405 int i, j, i2; 00406 00407 float uv_width = (float)(warp.bufferwidth) / warp.imagesize; 00408 float uv_height = (float)(warp.bufferheight) / warp.imagesize; 00409 00410 if(warp.mode ==2 ){ 00411 glBegin(GL_QUADS); 00412 for (i=0;i<warp.n_height-1;i++) { 00413 for (j=0;j<warp.n_width-1;j++) { 00414 if(warp.nodes[i][j].i < 0 || warp.nodes[i+1][j].i < 0 || warp.nodes[i+1][j+1].i < 0 || warp.nodes[i][j+1].i < 0) 00415 continue; 00416 00417 glColor3f(warp.nodes[i][j].i, warp.nodes[i][j].i, warp.nodes[i][j].i); 00418 glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height)); 00419 glVertex3f(warp.nodes[i][j].x, warp.nodes[i][j].y,0.0); 00420 00421 glColor3f(warp.nodes[i+1][j].i, warp.nodes[i+1][j].i, warp.nodes[i+1][j].i); 00422 glTexCoord2f((warp.nodes[i+1][j].u * uv_width), (warp.nodes[i+1][j].v * uv_height)); 00423 glVertex3f(warp.nodes[i+1][j].x, warp.nodes[i+1][j].y,0.0); 00424 00425 glColor3f(warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i); 00426 glTexCoord2f((warp.nodes[i+1][j+1].u * uv_width), (warp.nodes[i+1][j+1].v * uv_height)); 00427 glVertex3f(warp.nodes[i+1][j+1].x, warp.nodes[i+1][j+1].y,0.0); 00428 00429 glColor3f(warp.nodes[i][j+1].i, warp.nodes[i][j+1].i, warp.nodes[i][j+1].i); 00430 glTexCoord2f((warp.nodes[i][j+1].u * uv_width), (warp.nodes[i][j+1].v * uv_height)); 00431 glVertex3f(warp.nodes[i][j+1].x, warp.nodes[i][j+1].y,0.0); 00432 } 00433 } 00434 glEnd(); 00435 } 00436 else if (warp.mode == 1){ 00437 glBegin(GL_QUADS); 00438 for (i=0;i<warp.n_height-1;i++) { 00439 for (j=0;j<warp.n_width-1;j++) { 00440 i2 = (i+1) % warp.n_width; // Wrap around, i = warp.n_width = 0 00441 00442 if (warp.nodes[i][j].i < 0 || warp.nodes[i2][j].i < 0 || warp.nodes[i2][j+1].i < 0 || warp.nodes[i][j+1].i < 0) 00443 continue; 00444 00445 glColor3f(warp.nodes[i][j].i,warp.nodes[i][j].i,warp.nodes[i][j].i); 00446 glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height)); 00447 glVertex3f(warp.nodes[i][j].x,warp.nodes[i][j].y,0.0); 00448 00449 glColor3f(warp.nodes[i2][j].i,warp.nodes[i2][j].i,warp.nodes[i2][j].i); 00450 glTexCoord2f((warp.nodes[i2][j].u * uv_width), (warp.nodes[i2][j].v * uv_height)); 00451 glVertex3f(warp.nodes[i2][j].x,warp.nodes[i2][j].y,0.0); 00452 00453 glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i); 00454 glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height)); 00455 glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0); 00456 00457 glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i); 00458 glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height)); 00459 glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0); 00460 00461 } 00462 } 00463 glEnd(); 00464 } else{ 00465 printf("Dome Error: Warp Mode %d unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n", warp.mode); 00466 } 00467 } 00468 00469 00470 bool KX_Dome::ParseWarpMesh(STR_String text) 00471 { 00472 /* 00473 //Notes about the supported data format: 00474 File example:: 00475 mode 00476 width height 00477 n0_x n0_y n0_u n0_v n0_i 00478 n1_x n1_y n1_u n1_v n1_i 00479 n2_x n1_y n2_u n2_v n2_i 00480 n3_x n3_y n3_u n3_v n3_i 00481 (...) 00482 First line is the image type the mesh is support to be applied to: 2 = fisheye, 1=radial 00483 Tthe next line has the mesh dimensions 00484 Rest of the lines are the nodes of the mesh. Each line has x y u v i 00485 (x,y) are the normalised screen coordinates 00486 (u,v) texture coordinates 00487 i a multiplicative intensity factor 00488 00489 x varies from -screen aspect to screen aspect 00490 y varies from -1 to 1 00491 u and v vary from 0 to 1 00492 i ranges from 0 to 1, if negative don't draw that mesh node 00493 */ 00494 int i; 00495 int nodeX=0, nodeY=0; 00496 00497 vector<STR_String> columns, lines; 00498 00499 lines = text.Explode('\n'); 00500 if(lines.size() < 6){ 00501 printf("Dome Error: Warp Mesh File with insufficient data!\n"); 00502 return false; 00503 } 00504 columns = lines[1].Explode(' '); 00505 if(columns.size() == 1) 00506 columns = lines[1].Explode('\t'); 00507 00508 if(columns.size() !=2){ 00509 printf("Dome Error: Warp Mesh File incorrect. The second line should contain: width height.\n"); 00510 return false; 00511 } 00512 00513 warp.mode = atoi(lines[0]);// 1 = radial, 2 = fisheye 00514 00515 warp.n_width = atoi(columns[0]); 00516 warp.n_height = atoi(columns[1]); 00517 00518 if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)){ 00519 printf("Dome Error: Warp Mesh File with insufficient data!\n"); 00520 return false; 00521 }else{ 00522 warp.nodes = vector<vector<WarpMeshNode> > (warp.n_height, vector<WarpMeshNode>(warp.n_width)); 00523 00524 for(i=2; i-2 < (warp.n_width*warp.n_height); i++){ 00525 columns = lines[i].Explode(' '); 00526 if(columns.size() == 1) 00527 columns = lines[i].Explode('\t'); 00528 00529 if (columns.size() == 5){ 00530 nodeX = (i-2)%warp.n_width; 00531 nodeY = ((i-2) - nodeX) / warp.n_width; 00532 00533 warp.nodes[nodeY][nodeX].x = atof(columns[0]); 00534 warp.nodes[nodeY][nodeX].y = atof(columns[1]); 00535 warp.nodes[nodeY][nodeX].u = atof(columns[2]); 00536 warp.nodes[nodeY][nodeX].v = atof(columns[3]); 00537 warp.nodes[nodeY][nodeX].i = atof(columns[4]); 00538 } 00539 else{ 00540 warp.nodes.clear(); 00541 printf("Dome Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n"); 00542 return false; 00543 } 00544 } 00545 } 00546 return true; 00547 } 00548 00549 void KX_Dome::CreateMeshDome180(void) 00550 { 00551 /* 00552 1)- Define the faces of half of a cube 00553 - each face is made out of 2 triangles 00554 2) Subdivide the faces 00555 - more resolution == more curved lines 00556 3) Spherize the cube 00557 - normalize the verts 00558 4) Flatten onto xz plane 00559 - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image 00560 */ 00561 int i,j; 00562 float uv_ratio = (float)(m_buffersize-1) / m_imagesize; 00563 00564 m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening 00565 00566 //creating faces for the env mapcube 180deg Dome 00567 // Top Face - just a triangle 00568 cubetop[0].verts[0][0] = -M_SQRT2 / 2.0; 00569 cubetop[0].verts[0][1] = 0.0; 00570 cubetop[0].verts[0][2] = 0.5; 00571 cubetop[0].u[0] = 0.0; 00572 cubetop[0].v[0] = uv_ratio; 00573 00574 cubetop[0].verts[1][0] = 0.0; 00575 cubetop[0].verts[1][1] = M_SQRT2 / 2.0; 00576 cubetop[0].verts[1][2] = 0.5; 00577 cubetop[0].u[1] = 0.0; 00578 cubetop[0].v[1] = 0.0; 00579 00580 cubetop[0].verts[2][0] = M_SQRT2 / 2.0; 00581 cubetop[0].verts[2][1] = 0.0; 00582 cubetop[0].verts[2][2] = 0.5; 00583 cubetop[0].u[2] = uv_ratio; 00584 cubetop[0].v[2] = 0.0; 00585 00586 nfacestop = 1; 00587 00588 /* Bottom face - just a triangle */ 00589 cubebottom[0].verts[0][0] = -M_SQRT2 / 2.0; 00590 cubebottom[0].verts[0][1] = 0.0; 00591 cubebottom[0].verts[0][2] = -0.5; 00592 cubebottom[0].u[0] = uv_ratio; 00593 cubebottom[0].v[0] = 0.0; 00594 00595 cubebottom[0].verts[1][0] = M_SQRT2 / 2.0; 00596 cubebottom[0].verts[1][1] = 0; 00597 cubebottom[0].verts[1][2] = -0.5; 00598 cubebottom[0].u[1] = 0.0; 00599 cubebottom[0].v[1] = uv_ratio; 00600 00601 cubebottom[0].verts[2][0] = 0.0; 00602 cubebottom[0].verts[2][1] = M_SQRT2 / 2.0; 00603 cubebottom[0].verts[2][2] = -0.5; 00604 cubebottom[0].u[2] = 0.0; 00605 cubebottom[0].v[2] = 0.0; 00606 00607 nfacesbottom = 1; 00608 00609 /* Left face - two triangles */ 00610 00611 cubeleft[0].verts[0][0] = -M_SQRT2 / 2.0; 00612 cubeleft[0].verts[0][1] = .0; 00613 cubeleft[0].verts[0][2] = -0.5; 00614 cubeleft[0].u[0] = 0.0; 00615 cubeleft[0].v[0] = 0.0; 00616 00617 cubeleft[0].verts[1][0] = 0.0; 00618 cubeleft[0].verts[1][1] = M_SQRT2 / 2.0; 00619 cubeleft[0].verts[1][2] = -0.5; 00620 cubeleft[0].u[1] = uv_ratio; 00621 cubeleft[0].v[1] = 0.0; 00622 00623 cubeleft[0].verts[2][0] = -M_SQRT2 / 2.0; 00624 cubeleft[0].verts[2][1] = 0.0; 00625 cubeleft[0].verts[2][2] = 0.5; 00626 cubeleft[0].u[2] = 0.0; 00627 cubeleft[0].v[2] = uv_ratio; 00628 00629 //second triangle 00630 cubeleft[1].verts[0][0] = -M_SQRT2 / 2.0; 00631 cubeleft[1].verts[0][1] = 0.0; 00632 cubeleft[1].verts[0][2] = 0.5; 00633 cubeleft[1].u[0] = 0.0; 00634 cubeleft[1].v[0] = uv_ratio; 00635 00636 cubeleft[1].verts[1][0] = 0.0; 00637 cubeleft[1].verts[1][1] = M_SQRT2 / 2.0; 00638 cubeleft[1].verts[1][2] = -0.5; 00639 cubeleft[1].u[1] = uv_ratio; 00640 cubeleft[1].v[1] = 0.0; 00641 00642 cubeleft[1].verts[2][0] = 0.0; 00643 cubeleft[1].verts[2][1] = M_SQRT2 / 2.0; 00644 cubeleft[1].verts[2][2] = 0.5; 00645 cubeleft[1].u[2] = uv_ratio; 00646 cubeleft[1].v[2] = uv_ratio; 00647 00648 nfacesleft = 2; 00649 00650 /* Right face - two triangles */ 00651 cuberight[0].verts[0][0] = 0.0; 00652 cuberight[0].verts[0][1] = M_SQRT2 / 2.0; 00653 cuberight[0].verts[0][2] = -0.5; 00654 cuberight[0].u[0] = 0.0; 00655 cuberight[0].v[0] = 0.0; 00656 00657 cuberight[0].verts[1][0] = M_SQRT2 / 2.0; 00658 cuberight[0].verts[1][1] = 0.0; 00659 cuberight[0].verts[1][2] = -0.5; 00660 cuberight[0].u[1] = uv_ratio; 00661 cuberight[0].v[1] = 0.0; 00662 00663 cuberight[0].verts[2][0] = M_SQRT2 / 2.0; 00664 cuberight[0].verts[2][1] = 0.0; 00665 cuberight[0].verts[2][2] = 0.5; 00666 cuberight[0].u[2] = uv_ratio; 00667 cuberight[0].v[2] = uv_ratio; 00668 00669 //second triangle 00670 cuberight[1].verts[0][0] = 0.0; 00671 cuberight[1].verts[0][1] = M_SQRT2 / 2.0; 00672 cuberight[1].verts[0][2] = -0.5; 00673 cuberight[1].u[0] = 0.0; 00674 cuberight[1].v[0] = 0.0; 00675 00676 cuberight[1].verts[1][0] = M_SQRT2 / 2.0; 00677 cuberight[1].verts[1][1] = 0.0; 00678 cuberight[1].verts[1][2] = 0.5; 00679 cuberight[1].u[1] = uv_ratio; 00680 cuberight[1].v[1] = uv_ratio; 00681 00682 cuberight[1].verts[2][0] = 0.0; 00683 cuberight[1].verts[2][1] = M_SQRT2 / 2.0; 00684 cuberight[1].verts[2][2] = 0.5; 00685 cuberight[1].u[2] = 0.0; 00686 cuberight[1].v[2] = uv_ratio; 00687 00688 nfacesright = 2; 00689 00690 //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration 00691 //Could be made more efficient for drawing if the triangles were ordered in a fan. Not that important since we are using DisplayLists 00692 00693 for(i=0;i<m_resolution;i++){ 00694 cubetop.resize(4*nfacestop); 00695 SplitFace(cubetop,&nfacestop); 00696 cubebottom.resize(4*nfacesbottom); 00697 SplitFace(cubebottom,&nfacesbottom); 00698 cubeleft.resize(4*nfacesleft); 00699 SplitFace(cubeleft,&nfacesleft); 00700 cuberight.resize(4*nfacesright); 00701 SplitFace(cuberight,&nfacesright); 00702 } 00703 00704 // Turn into a hemisphere 00705 for(j=0;j<3;j++){ 00706 for(i=0;i<nfacestop;i++) 00707 cubetop[i].verts[j].normalize(); 00708 for(i=0;i<nfacesbottom;i++) 00709 cubebottom[i].verts[j].normalize(); 00710 for(i=0;i<nfacesleft;i++) 00711 cubeleft[i].verts[j].normalize(); 00712 for(i=0;i<nfacesright;i++) 00713 cuberight[i].verts[j].normalize(); 00714 } 00715 00716 //flatten onto xz plane 00717 for(i=0;i<nfacestop;i++) 00718 FlattenDome(cubetop[i].verts); 00719 for(i=0;i<nfacesbottom;i++) 00720 FlattenDome(cubebottom[i].verts); 00721 for(i=0;i<nfacesleft;i++) 00722 FlattenDome(cubeleft[i].verts); 00723 for(i=0;i<nfacesright;i++) 00724 FlattenDome(cuberight[i].verts); 00725 00726 } 00727 00728 void KX_Dome::CreateMeshDome250(void) 00729 { 00730 /* 00731 1)- Define the faces of a cube without the back face 00732 - each face is made out of 2 triangles 00733 2) Subdivide the faces 00734 - more resolution == more curved lines 00735 3) Spherize the cube 00736 - normalize the verts 00737 4) Flatten onto xz plane 00738 - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image 00739 */ 00740 00741 int i,j; 00742 float uv_height, uv_base; 00743 float verts_height; 00744 00745 float rad_ang = m_angle * MT_PI / 180.0; 00746 float uv_ratio = (float)(m_buffersize-1) / m_imagesize; 00747 00748 m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening 00749 /* 00750 verts_height is the exactly needed height of the cube faces (not always 1.0). 00751 When we want some horizontal information (e.g. for horizontal 220deg domes) we don't need to create and tesselate the whole cube. 00752 Therefore the lateral cube faces could be small, and the tesselate mesh would be completely used. 00753 (if we always worked with verts_height = 1.0, we would be discarding a lot of the calculated and tesselated geometry). 00754 00755 So I came out with this formula: 00756 verts_height = tan((rad_ang/2) - (MT_PI/2))*sqrt(2.0); 00757 00758 Here we take half the sphere(rad_ang/2) and subtract a quarter of it (MT_PI/2) 00759 Therefore we have the length in radians of the dome/sphere over the horizon. 00760 Once we take the tangent of that angle, you have the verts coordinate corresponding to the verts on the side faces. 00761 Then we need to multiply it by sqrt(2.0) to get the coordinate of the verts on the diagonal of the original cube. 00762 */ 00763 verts_height = tan((rad_ang/2) - (MT_PI/2))*M_SQRT2; 00764 00765 uv_height = uv_ratio * ((verts_height/2) + 0.5); 00766 uv_base = uv_ratio * (1.0 - ((verts_height/2) + 0.5)); 00767 00768 //creating faces for the env mapcube 180deg Dome 00769 // Front Face - 2 triangles 00770 cubefront[0].verts[0][0] =-1.0; 00771 cubefront[0].verts[0][1] = 1.0; 00772 cubefront[0].verts[0][2] =-1.0; 00773 cubefront[0].u[0] = 0.0; 00774 cubefront[0].v[0] = 0.0; 00775 00776 cubefront[0].verts[1][0] = 1.0; 00777 cubefront[0].verts[1][1] = 1.0; 00778 cubefront[0].verts[1][2] = 1.0; 00779 cubefront[0].u[1] = uv_ratio; 00780 cubefront[0].v[1] = uv_ratio; 00781 00782 cubefront[0].verts[2][0] =-1.0; 00783 cubefront[0].verts[2][1] = 1.0; 00784 cubefront[0].verts[2][2] = 1.0; 00785 cubefront[0].u[2] = 0.0; 00786 cubefront[0].v[2] = uv_ratio; 00787 00788 //second triangle 00789 cubefront[1].verts[0][0] = 1.0; 00790 cubefront[1].verts[0][1] = 1.0; 00791 cubefront[1].verts[0][2] = 1.0; 00792 cubefront[1].u[0] = uv_ratio; 00793 cubefront[1].v[0] = uv_ratio; 00794 00795 cubefront[1].verts[1][0] =-1.0; 00796 cubefront[1].verts[1][1] = 1.0; 00797 cubefront[1].verts[1][2] =-1.0; 00798 cubefront[1].u[1] = 0.0; 00799 cubefront[1].v[1] = 0.0; 00800 00801 cubefront[1].verts[2][0] = 1.0; 00802 cubefront[1].verts[2][1] = 1.0; 00803 cubefront[1].verts[2][2] =-1.0; 00804 cubefront[1].u[2] = uv_ratio; 00805 cubefront[1].v[2] = 0.0; 00806 00807 nfacesfront = 2; 00808 00809 // Left Face - 2 triangles 00810 cubeleft[0].verts[0][0] =-1.0; 00811 cubeleft[0].verts[0][1] = 1.0; 00812 cubeleft[0].verts[0][2] =-1.0; 00813 cubeleft[0].u[0] = uv_ratio; 00814 cubeleft[0].v[0] = 0.0; 00815 00816 cubeleft[0].verts[1][0] =-1.0; 00817 cubeleft[0].verts[1][1] =-verts_height; 00818 cubeleft[0].verts[1][2] = 1.0; 00819 cubeleft[0].u[1] = uv_base; 00820 cubeleft[0].v[1] = uv_ratio; 00821 00822 cubeleft[0].verts[2][0] =-1.0; 00823 cubeleft[0].verts[2][1] =-verts_height; 00824 cubeleft[0].verts[2][2] =-1.0; 00825 cubeleft[0].u[2] = uv_base; 00826 cubeleft[0].v[2] = 0.0; 00827 00828 //second triangle 00829 cubeleft[1].verts[0][0] =-1.0; 00830 cubeleft[1].verts[0][1] =-verts_height; 00831 cubeleft[1].verts[0][2] = 1.0; 00832 cubeleft[1].u[0] = uv_base; 00833 cubeleft[1].v[0] = uv_ratio; 00834 00835 cubeleft[1].verts[1][0] =-1.0; 00836 cubeleft[1].verts[1][1] = 1.0; 00837 cubeleft[1].verts[1][2] =-1.0; 00838 cubeleft[1].u[1] = uv_ratio; 00839 cubeleft[1].v[1] = 0.0; 00840 00841 cubeleft[1].verts[2][0] =-1.0; 00842 cubeleft[1].verts[2][1] = 1.0; 00843 cubeleft[1].verts[2][2] = 1.0; 00844 cubeleft[1].u[2] = uv_ratio; 00845 cubeleft[1].v[2] = uv_ratio; 00846 00847 nfacesleft = 2; 00848 00849 // right Face - 2 triangles 00850 cuberight[0].verts[0][0] = 1.0; 00851 cuberight[0].verts[0][1] = 1.0; 00852 cuberight[0].verts[0][2] = 1.0; 00853 cuberight[0].u[0] = 0.0; 00854 cuberight[0].v[0] = uv_ratio; 00855 00856 cuberight[0].verts[1][0] = 1.0; 00857 cuberight[0].verts[1][1] =-verts_height; 00858 cuberight[0].verts[1][2] =-1.0; 00859 cuberight[0].u[1] = uv_height; 00860 cuberight[0].v[1] = 0.0; 00861 00862 cuberight[0].verts[2][0] = 1.0; 00863 cuberight[0].verts[2][1] =-verts_height; 00864 cuberight[0].verts[2][2] = 1.0; 00865 cuberight[0].u[2] = uv_height; 00866 cuberight[0].v[2] = uv_ratio; 00867 00868 //second triangle 00869 cuberight[1].verts[0][0] = 1.0; 00870 cuberight[1].verts[0][1] =-verts_height; 00871 cuberight[1].verts[0][2] =-1.0; 00872 cuberight[1].u[0] = uv_height; 00873 cuberight[1].v[0] = 0.0; 00874 00875 cuberight[1].verts[1][0] = 1.0; 00876 cuberight[1].verts[1][1] = 1.0; 00877 cuberight[1].verts[1][2] = 1.0; 00878 cuberight[1].u[1] = 0.0; 00879 cuberight[1].v[1] = uv_ratio; 00880 00881 cuberight[1].verts[2][0] = 1.0; 00882 cuberight[1].verts[2][1] = 1.0; 00883 cuberight[1].verts[2][2] =-1.0; 00884 cuberight[1].u[2] = 0.0; 00885 cuberight[1].v[2] = 0.0; 00886 00887 nfacesright = 2; 00888 00889 // top Face - 2 triangles 00890 cubetop[0].verts[0][0] =-1.0; 00891 cubetop[0].verts[0][1] = 1.0; 00892 cubetop[0].verts[0][2] = 1.0; 00893 cubetop[0].u[0] = 0.0; 00894 cubetop[0].v[0] = 0.0; 00895 00896 cubetop[0].verts[1][0] = 1.0; 00897 cubetop[0].verts[1][1] =-verts_height; 00898 cubetop[0].verts[1][2] = 1.0; 00899 cubetop[0].u[1] = uv_ratio; 00900 cubetop[0].v[1] = uv_height; 00901 00902 cubetop[0].verts[2][0] =-1.0; 00903 cubetop[0].verts[2][1] =-verts_height; 00904 cubetop[0].verts[2][2] = 1.0; 00905 cubetop[0].u[2] = 0.0; 00906 cubetop[0].v[2] = uv_height; 00907 00908 //second triangle 00909 cubetop[1].verts[0][0] = 1.0; 00910 cubetop[1].verts[0][1] =-verts_height; 00911 cubetop[1].verts[0][2] = 1.0; 00912 cubetop[1].u[0] = uv_ratio; 00913 cubetop[1].v[0] = uv_height; 00914 00915 cubetop[1].verts[1][0] =-1.0; 00916 cubetop[1].verts[1][1] = 1.0; 00917 cubetop[1].verts[1][2] = 1.0; 00918 cubetop[1].u[1] = 0.0; 00919 cubetop[1].v[1] = 0.0; 00920 00921 cubetop[1].verts[2][0] = 1.0; 00922 cubetop[1].verts[2][1] = 1.0; 00923 cubetop[1].verts[2][2] = 1.0; 00924 cubetop[1].u[2] = uv_ratio; 00925 cubetop[1].v[2] = 0.0; 00926 00927 nfacestop = 2; 00928 00929 // bottom Face - 2 triangles 00930 cubebottom[0].verts[0][0] =-1.0; 00931 cubebottom[0].verts[0][1] =-verts_height; 00932 cubebottom[0].verts[0][2] =-1.0; 00933 cubebottom[0].u[0] = 0.0; 00934 cubebottom[0].v[0] = uv_base; 00935 00936 cubebottom[0].verts[1][0] = 1.0; 00937 cubebottom[0].verts[1][1] = 1.0; 00938 cubebottom[0].verts[1][2] =-1.0; 00939 cubebottom[0].u[1] = uv_ratio; 00940 cubebottom[0].v[1] = uv_ratio; 00941 00942 cubebottom[0].verts[2][0] =-1.0; 00943 cubebottom[0].verts[2][1] = 1.0; 00944 cubebottom[0].verts[2][2] =-1.0; 00945 cubebottom[0].u[2] = 0.0; 00946 cubebottom[0].v[2] = uv_ratio; 00947 00948 //second triangle 00949 cubebottom[1].verts[0][0] = 1.0; 00950 cubebottom[1].verts[0][1] = 1.0; 00951 cubebottom[1].verts[0][2] =-1.0; 00952 cubebottom[1].u[0] = uv_ratio; 00953 cubebottom[1].v[0] = uv_ratio; 00954 00955 cubebottom[1].verts[1][0] =-1.0; 00956 cubebottom[1].verts[1][1] =-verts_height; 00957 cubebottom[1].verts[1][2] =-1.0; 00958 cubebottom[1].u[1] = 0.0; 00959 cubebottom[1].v[1] = uv_base; 00960 00961 cubebottom[1].verts[2][0] = 1.0; 00962 cubebottom[1].verts[2][1] =-verts_height; 00963 cubebottom[1].verts[2][2] =-1.0; 00964 cubebottom[1].u[2] = uv_ratio; 00965 cubebottom[1].v[2] = uv_base; 00966 00967 nfacesbottom = 2; 00968 00969 //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration 00970 //It could be made more efficient for drawing if the triangles were ordered in a strip! 00971 00972 for(i=0;i<m_resolution;i++){ 00973 cubefront.resize(4*nfacesfront); 00974 SplitFace(cubefront,&nfacesfront); 00975 cubetop.resize(4*nfacestop); 00976 SplitFace(cubetop,&nfacestop); 00977 cubebottom.resize(4*nfacesbottom); 00978 SplitFace(cubebottom,&nfacesbottom); 00979 cubeleft.resize(4*nfacesleft); 00980 SplitFace(cubeleft,&nfacesleft); 00981 cuberight.resize(4*nfacesright); 00982 SplitFace(cuberight,&nfacesright); 00983 } 00984 00985 // Turn into a hemisphere/sphere 00986 for(j=0;j<3;j++){ 00987 for(i=0;i<nfacesfront;i++) 00988 cubefront[i].verts[j].normalize(); 00989 for(i=0;i<nfacestop;i++) 00990 cubetop[i].verts[j].normalize(); 00991 for(i=0;i<nfacesbottom;i++) 00992 cubebottom[i].verts[j].normalize(); 00993 for(i=0;i<nfacesleft;i++) 00994 cubeleft[i].verts[j].normalize(); 00995 for(i=0;i<nfacesright;i++) 00996 cuberight[i].verts[j].normalize(); 00997 } 00998 00999 //flatten onto xz plane 01000 for(i=0;i<nfacesfront;i++) 01001 FlattenDome(cubefront[i].verts); 01002 for(i=0;i<nfacestop;i++) 01003 FlattenDome(cubetop[i].verts); 01004 for(i=0;i<nfacesbottom;i++) 01005 FlattenDome(cubebottom[i].verts); 01006 for(i=0;i<nfacesleft;i++) 01007 FlattenDome(cubeleft[i].verts); 01008 for(i=0;i<nfacesright;i++) 01009 FlattenDome(cuberight[i].verts); 01010 } 01011 01012 void KX_Dome::CreateMeshPanorama(void) 01013 { 01014 /* 01015 1)- Define the faces of a cube without the top and bottom faces 01016 - each face is made out of 2 triangles 01017 2) Subdivide the faces 01018 - more resolution == more curved lines 01019 3) Spherize the cube 01020 - normalize the verts t 01021 4) Flatten onto xz plane 01022 - use spherical projection techniques to transform the sphere onto a flat panorama 01023 */ 01024 int i,j; 01025 01026 float uv_ratio = (float)(m_buffersize-1) / m_imagesize; 01027 01028 /* Top face - two triangles */ 01029 cubetop[0].verts[0][0] = -M_SQRT2; 01030 cubetop[0].verts[0][1] = 0.0; 01031 cubetop[0].verts[0][2] = 1.0; 01032 cubetop[0].u[0] = 0.0; 01033 cubetop[0].v[0] = uv_ratio; 01034 01035 cubetop[0].verts[1][0] = 0.0; 01036 cubetop[0].verts[1][1] = M_SQRT2; 01037 cubetop[0].verts[1][2] = 1.0; 01038 cubetop[0].u[1] = 0.0; 01039 cubetop[0].v[1] = 0.0; 01040 01041 //second triangle 01042 cubetop[0].verts[2][0] = M_SQRT2; 01043 cubetop[0].verts[2][1] = 0.0; 01044 cubetop[0].verts[2][2] = 1.0; 01045 cubetop[0].u[2] = uv_ratio; 01046 cubetop[0].v[2] = 0.0; 01047 01048 cubetop[1].verts[0][0] = M_SQRT2; 01049 cubetop[1].verts[0][1] = 0.0; 01050 cubetop[1].verts[0][2] = 1.0; 01051 cubetop[1].u[0] = uv_ratio; 01052 cubetop[1].v[0] = 0.0; 01053 01054 cubetop[1].verts[1][0] = 0.0; 01055 cubetop[1].verts[1][1] = -M_SQRT2; 01056 cubetop[1].verts[1][2] = 1.0; 01057 cubetop[1].u[1] = uv_ratio; 01058 cubetop[1].v[1] = uv_ratio; 01059 01060 cubetop[1].verts[2][0] = -M_SQRT2; 01061 cubetop[1].verts[2][1] = 0.0; 01062 cubetop[1].verts[2][2] = 1.0; 01063 cubetop[1].u[2] = 0.0; 01064 cubetop[1].v[2] = uv_ratio; 01065 01066 nfacestop = 2; 01067 01068 /* Bottom face - two triangles */ 01069 cubebottom[0].verts[0][0] = -M_SQRT2; 01070 cubebottom[0].verts[0][1] = 0.0; 01071 cubebottom[0].verts[0][2] = -1.0; 01072 cubebottom[0].u[0] = uv_ratio; 01073 cubebottom[0].v[0] = 0.0; 01074 01075 cubebottom[0].verts[1][0] = M_SQRT2; 01076 cubebottom[0].verts[1][1] = 0.0; 01077 cubebottom[0].verts[1][2] = -1.0; 01078 cubebottom[0].u[1] = 0.0; 01079 cubebottom[0].v[1] = uv_ratio; 01080 01081 cubebottom[0].verts[2][0] = 0.0; 01082 cubebottom[0].verts[2][1] = M_SQRT2; 01083 cubebottom[0].verts[2][2] = -1.0; 01084 cubebottom[0].u[2] = 0.0; 01085 cubebottom[0].v[2] = 0.0; 01086 01087 //second triangle 01088 cubebottom[1].verts[0][0] = M_SQRT2; 01089 cubebottom[1].verts[0][1] = 0.0; 01090 cubebottom[1].verts[0][2] = -1.0; 01091 cubebottom[1].u[0] = 0.0; 01092 cubebottom[1].v[0] = uv_ratio; 01093 01094 cubebottom[1].verts[1][0] = -M_SQRT2; 01095 cubebottom[1].verts[1][1] = 0.0; 01096 cubebottom[1].verts[1][2] = -1.0; 01097 cubebottom[1].u[1] = uv_ratio; 01098 cubebottom[1].v[1] = 0.0; 01099 01100 cubebottom[1].verts[2][0] = 0.0; 01101 cubebottom[1].verts[2][1] = -M_SQRT2; 01102 cubebottom[1].verts[2][2] = -1.0; 01103 cubebottom[1].u[2] = uv_ratio; 01104 cubebottom[1].v[2] = uv_ratio; 01105 01106 nfacesbottom = 2; 01107 01108 /* Left Back (135deg) face - two triangles */ 01109 01110 cubeleftback[0].verts[0][0] = 0; 01111 cubeleftback[0].verts[0][1] = -M_SQRT2; 01112 cubeleftback[0].verts[0][2] = -1.0; 01113 cubeleftback[0].u[0] = 0; 01114 cubeleftback[0].v[0] = 0; 01115 01116 cubeleftback[0].verts[1][0] = -M_SQRT2; 01117 cubeleftback[0].verts[1][1] = 0; 01118 cubeleftback[0].verts[1][2] = -1.0; 01119 cubeleftback[0].u[1] = uv_ratio; 01120 cubeleftback[0].v[1] = 0; 01121 01122 cubeleftback[0].verts[2][0] = 0; 01123 cubeleftback[0].verts[2][1] = -M_SQRT2; 01124 cubeleftback[0].verts[2][2] = 1.0; 01125 cubeleftback[0].u[2] = 0; 01126 cubeleftback[0].v[2] = uv_ratio; 01127 01128 //second triangle 01129 cubeleftback[1].verts[0][0] = 0; 01130 cubeleftback[1].verts[0][1] = -M_SQRT2; 01131 cubeleftback[1].verts[0][2] = 1.0; 01132 cubeleftback[1].u[0] = 0; 01133 cubeleftback[1].v[0] = uv_ratio; 01134 01135 cubeleftback[1].verts[1][0] = -M_SQRT2; 01136 cubeleftback[1].verts[1][1] = 0; 01137 cubeleftback[1].verts[1][2] = -1.0; 01138 cubeleftback[1].u[1] = uv_ratio; 01139 cubeleftback[1].v[1] = 0; 01140 01141 cubeleftback[1].verts[2][0] = -M_SQRT2; 01142 cubeleftback[1].verts[2][1] = 0; 01143 cubeleftback[1].verts[2][2] = 1.0; 01144 cubeleftback[1].u[2] = uv_ratio; 01145 cubeleftback[1].v[2] = uv_ratio; 01146 01147 nfacesleftback = 2; 01148 01149 /* Left face - two triangles */ 01150 01151 cubeleft[0].verts[0][0] = -M_SQRT2; 01152 cubeleft[0].verts[0][1] = 0; 01153 cubeleft[0].verts[0][2] = -1.0; 01154 cubeleft[0].u[0] = 0; 01155 cubeleft[0].v[0] = 0; 01156 01157 cubeleft[0].verts[1][0] = 0; 01158 cubeleft[0].verts[1][1] = M_SQRT2; 01159 cubeleft[0].verts[1][2] = -1.0; 01160 cubeleft[0].u[1] = uv_ratio; 01161 cubeleft[0].v[1] = 0; 01162 01163 cubeleft[0].verts[2][0] = -M_SQRT2; 01164 cubeleft[0].verts[2][1] = 0; 01165 cubeleft[0].verts[2][2] = 1.0; 01166 cubeleft[0].u[2] = 0; 01167 cubeleft[0].v[2] = uv_ratio; 01168 01169 //second triangle 01170 cubeleft[1].verts[0][0] = -M_SQRT2; 01171 cubeleft[1].verts[0][1] = 0; 01172 cubeleft[1].verts[0][2] = 1.0; 01173 cubeleft[1].u[0] = 0; 01174 cubeleft[1].v[0] = uv_ratio; 01175 01176 cubeleft[1].verts[1][0] = 0; 01177 cubeleft[1].verts[1][1] = M_SQRT2; 01178 cubeleft[1].verts[1][2] = -1.0; 01179 cubeleft[1].u[1] = uv_ratio; 01180 cubeleft[1].v[1] = 0; 01181 01182 cubeleft[1].verts[2][0] = 0; 01183 cubeleft[1].verts[2][1] = M_SQRT2; 01184 cubeleft[1].verts[2][2] = 1.0; 01185 cubeleft[1].u[2] = uv_ratio; 01186 cubeleft[1].v[2] = uv_ratio; 01187 01188 nfacesleft = 2; 01189 01190 /* Right face - two triangles */ 01191 cuberight[0].verts[0][0] = 0; 01192 cuberight[0].verts[0][1] = M_SQRT2; 01193 cuberight[0].verts[0][2] = -1.0; 01194 cuberight[0].u[0] = 0; 01195 cuberight[0].v[0] = 0; 01196 01197 cuberight[0].verts[1][0] = M_SQRT2; 01198 cuberight[0].verts[1][1] = 0; 01199 cuberight[0].verts[1][2] = -1.0; 01200 cuberight[0].u[1] = uv_ratio; 01201 cuberight[0].v[1] = 0; 01202 01203 cuberight[0].verts[2][0] = M_SQRT2; 01204 cuberight[0].verts[2][1] = 0; 01205 cuberight[0].verts[2][2] = 1.0; 01206 cuberight[0].u[2] = uv_ratio; 01207 cuberight[0].v[2] = uv_ratio; 01208 01209 //second triangle 01210 cuberight[1].verts[0][0] = 0; 01211 cuberight[1].verts[0][1] = M_SQRT2; 01212 cuberight[1].verts[0][2] = -1.0; 01213 cuberight[1].u[0] = 0; 01214 cuberight[1].v[0] = 0; 01215 01216 cuberight[1].verts[1][0] = M_SQRT2; 01217 cuberight[1].verts[1][1] = 0; 01218 cuberight[1].verts[1][2] = 1.0; 01219 cuberight[1].u[1] = uv_ratio; 01220 cuberight[1].v[1] = uv_ratio; 01221 01222 cuberight[1].verts[2][0] = 0; 01223 cuberight[1].verts[2][1] = M_SQRT2; 01224 cuberight[1].verts[2][2] = 1.0; 01225 cuberight[1].u[2] = 0; 01226 cuberight[1].v[2] = uv_ratio; 01227 01228 nfacesright = 2; 01229 01230 /* Right Back (-135deg) face - two triangles */ 01231 cuberightback[0].verts[0][0] = M_SQRT2; 01232 cuberightback[0].verts[0][1] = 0; 01233 cuberightback[0].verts[0][2] = -1.0; 01234 cuberightback[0].u[0] = 0; 01235 cuberightback[0].v[0] = 0; 01236 01237 cuberightback[0].verts[1][0] = 0; 01238 cuberightback[0].verts[1][1] = -M_SQRT2; 01239 cuberightback[0].verts[1][2] = -1.0; 01240 cuberightback[0].u[1] = uv_ratio; 01241 cuberightback[0].v[1] = 0; 01242 01243 cuberightback[0].verts[2][0] = 0; 01244 cuberightback[0].verts[2][1] = -M_SQRT2; 01245 cuberightback[0].verts[2][2] = 1.0; 01246 cuberightback[0].u[2] = uv_ratio; 01247 cuberightback[0].v[2] = uv_ratio; 01248 01249 //second triangle 01250 cuberightback[1].verts[0][0] = M_SQRT2; 01251 cuberightback[1].verts[0][1] = 0; 01252 cuberightback[1].verts[0][2] = -1.0; 01253 cuberightback[1].u[0] = 0; 01254 cuberightback[1].v[0] = 0; 01255 01256 cuberightback[1].verts[1][0] = 0; 01257 cuberightback[1].verts[1][1] = -M_SQRT2; 01258 cuberightback[1].verts[1][2] = 1.0; 01259 cuberightback[1].u[1] = uv_ratio; 01260 cuberightback[1].v[1] = uv_ratio; 01261 01262 cuberightback[1].verts[2][0] = M_SQRT2; 01263 cuberightback[1].verts[2][1] = 0; 01264 cuberightback[1].verts[2][2] = 1.0; 01265 cuberightback[1].u[2] = 0; 01266 cuberightback[1].v[2] = uv_ratio; 01267 01268 nfacesrightback = 2; 01269 01270 // Subdivide the faces 01271 for(i=0;i<m_resolution;i++) 01272 { 01273 cubetop.resize(4*nfacestop); 01274 SplitFace(cubetop,&nfacestop); 01275 01276 cubebottom.resize(4*nfacesbottom); 01277 SplitFace(cubebottom,&nfacesbottom); 01278 01279 cubeleft.resize(4*nfacesleft); 01280 SplitFace(cubeleft,&nfacesleft); 01281 01282 cuberight.resize(4*nfacesright); 01283 SplitFace(cuberight,&nfacesright); 01284 01285 cubeleftback.resize(4*nfacesleftback); 01286 SplitFace(cubeleftback,&nfacesleftback); 01287 01288 cuberightback.resize(4*nfacesrightback); 01289 SplitFace(cuberightback,&nfacesrightback); 01290 } 01291 01292 // Spherize the cube 01293 for(j=0;j<3;j++) 01294 { 01295 for(i=0;i<nfacestop;i++) 01296 cubetop[i].verts[j].normalize(); 01297 01298 for(i=0;i<nfacesbottom;i++) 01299 cubebottom[i].verts[j].normalize(); 01300 01301 for(i=0;i<nfacesleftback;i++) 01302 cubeleftback[i].verts[j].normalize(); 01303 01304 for(i=0;i<nfacesleft;i++) 01305 cubeleft[i].verts[j].normalize(); 01306 01307 for(i=0;i<nfacesright;i++) 01308 cuberight[i].verts[j].normalize(); 01309 01310 for(i=0;i<nfacesrightback;i++) 01311 cuberightback[i].verts[j].normalize(); 01312 } 01313 01314 //Flatten onto xz plane 01315 for(i=0;i<nfacesleftback;i++) 01316 FlattenPanorama(cubeleftback[i].verts); 01317 01318 for(i=0;i<nfacesleft;i++) 01319 FlattenPanorama(cubeleft[i].verts); 01320 01321 for(i=0;i<nfacesright;i++) 01322 FlattenPanorama(cuberight[i].verts); 01323 01324 for(i=0;i<nfacesrightback;i++) 01325 FlattenPanorama(cuberightback[i].verts); 01326 01327 for(i=0;i<nfacestop;i++) 01328 FlattenPanorama(cubetop[i].verts); 01329 01330 for(i=0;i<nfacesbottom;i++) 01331 FlattenPanorama(cubebottom[i].verts); 01332 } 01333 01334 void KX_Dome::FlattenDome(MT_Vector3 verts[3]) 01335 { 01336 double phi, r; 01337 01338 for (int i=0;i<3;i++){ 01339 r = atan2(sqrt(verts[i][0]*verts[i][0] + verts[i][2]*verts[i][2]), verts[i][1]); 01340 r /= m_radangle/2; 01341 01342 phi = atan2(verts[i][2], verts[i][0]); 01343 01344 verts[i][0] = r * cos(phi); 01345 verts[i][1] = 0; 01346 verts[i][2] = r * sin(phi); 01347 01348 if (r > 1.0){ 01349 //round the border 01350 verts[i][0] = cos(phi); 01351 verts[i][1] = -3.0; 01352 verts[i][2] = sin(phi); 01353 } 01354 } 01355 } 01356 01357 void KX_Dome::FlattenPanorama(MT_Vector3 verts[3]) 01358 { 01359 // it creates a full spherical panoramic (360deg) 01360 int i; 01361 double phi; 01362 bool edge=false; 01363 01364 for (i=0;i<3;i++){ 01365 phi = atan2(verts[i][1], verts[i][0]); 01366 phi *= -1.0; //flipping 01367 01368 if (phi == -MT_PI) //It's on the edge 01369 edge=true; 01370 01371 verts[i][0] = phi / MT_PI; 01372 verts[i][1] = 0; 01373 01374 verts[i][2] = atan2(verts[i][2], 1.0); 01375 verts[i][2] /= MT_PI / 2; 01376 } 01377 if(edge){ 01378 bool right=false; 01379 01380 for (i=0;i<3;i++){ 01381 if(fmod(verts[i][0],1.0) > 0.0){ 01382 right=true; 01383 break; 01384 } 01385 } 01386 if(right){ 01387 for (i=0;i<3;i++){ 01388 if(verts[i][0] < 0.0) 01389 verts[i][0] *= -1.0; 01390 } 01391 } 01392 } 01393 } 01394 01395 void KX_Dome::SplitFace(vector <DomeFace>& face, int *nfaces) 01396 { 01397 int i; 01398 int n1, n2; 01399 01400 n1 = n2 = *nfaces; 01401 01402 for(i=0;i<n1;i++){ 01403 01404 face[n2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2; 01405 face[n2].verts[1] = face[i].verts[1]; 01406 face[n2].verts[2] = (face[i].verts[1] + face[i].verts[2]) /2; 01407 face[n2].u[0] = (face[i].u[0] + face[i].u[1]) /2; 01408 face[n2].u[1] = face[i].u[1]; 01409 face[n2].u[2] = (face[i].u[1] + face[i].u[2]) /2; 01410 face[n2].v[0] = (face[i].v[0] + face[i].v[1]) /2; 01411 face[n2].v[1] = face[i].v[1]; 01412 face[n2].v[2] = (face[i].v[1] + face[i].v[2]) /2; 01413 01414 face[n2+1].verts[0] = (face[i].verts[1] + face[i].verts[2]) /2; 01415 face[n2+1].verts[1] = face[i].verts[2]; 01416 face[n2+1].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2; 01417 face[n2+1].u[0] = (face[i].u[1] + face[i].u[2]) /2; 01418 face[n2+1].u[1] = face[i].u[2]; 01419 face[n2+1].u[2] = (face[i].u[2] + face[i].u[0]) /2; 01420 face[n2+1].v[0] = (face[i].v[1] + face[i].v[2]) /2; 01421 face[n2+1].v[1] = face[i].v[2]; 01422 face[n2+1].v[2] = (face[i].v[2] + face[i].v[0]) /2; 01423 01424 face[n2+2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2; 01425 face[n2+2].verts[1] = (face[i].verts[1] + face[i].verts[2]) /2; 01426 face[n2+2].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2; 01427 face[n2+2].u[0] = (face[i].u[0] + face[i].u[1]) /2; 01428 face[n2+2].u[1] = (face[i].u[1] + face[i].u[2]) /2; 01429 face[n2+2].u[2] = (face[i].u[2] + face[i].u[0]) /2; 01430 face[n2+2].v[0] = (face[i].v[0] + face[i].v[1]) /2; 01431 face[n2+2].v[1] = (face[i].v[1] + face[i].v[2]) /2; 01432 face[n2+2].v[2] = (face[i].v[2] + face[i].v[0]) /2; 01433 01434 //face[i].verts[0] = face[i].verts[0] ; 01435 face[i].verts[1] = (face[i].verts[0] + face[i].verts[1]) /2; 01436 face[i].verts[2] = (face[i].verts[0] + face[i].verts[2]) /2; 01437 //face[i].u[0] = face[i].u[0]; 01438 face[i].u[1] = (face[i].u[0] + face[i].u[1]) /2; 01439 face[i].u[2] = (face[i].u[0] + face[i].u[2]) /2; 01440 //face[i].v[0] = face[i].v[0] ; 01441 face[i].v[1] = (face[i].v[0] + face[i].v[1]) /2; 01442 face[i].v[2] = (face[i].v[0] + face[i].v[2]) /2; 01443 01444 n2 += 3; // number of faces 01445 } 01446 *nfaces = n2; 01447 } 01448 01449 void KX_Dome::CalculateFrustum(KX_Camera * cam) 01450 { 01451 /* 01452 // manually creating a 90deg Field of View Frustum 01453 01454 the original formula: 01455 top = tan(fov*3.14159/360.0) * near [for fov in degrees] 01456 fov*0.5 = arctan ((top-bottom)*0.5 / near) [for fov in radians] 01457 bottom = -top 01458 left = aspect * bottom 01459 right = aspect * top 01460 01461 // the equivalent GLU call is: 01462 glMatrixMode(GL_PROJECTION); 01463 glLoadIdentity(); 01464 gluPerspective(90.0,1.0,cam->GetCameraNear(),cam->GetCameraFar()); 01465 */ 01466 01467 RAS_FrameFrustum m_frustrum; //90 deg. Frustum 01468 01469 m_frustrum.camnear = cam->GetCameraNear(); 01470 m_frustrum.camfar = cam->GetCameraFar(); 01471 01472 // float top = tan(90.0*MT_PI/360.0) * m_frustrum.camnear; 01473 float top = m_frustrum.camnear; // for deg = 90deg, tan = 1 01474 01475 m_frustrum.x1 = -top; 01476 m_frustrum.x2 = top; 01477 m_frustrum.y1 = -top; 01478 m_frustrum.y2 = top; 01479 01480 m_projmat = m_rasterizer->GetFrustumMatrix( 01481 m_frustrum.x1, m_frustrum.x2, m_frustrum.y1, m_frustrum.y2, m_frustrum.camnear, m_frustrum.camfar); 01482 01483 } 01484 01485 void KX_Dome::CalculateCameraOrientation() 01486 { 01487 /* 01488 Uses 4 cameras for angles up to 180deg 01489 Uses 5 cameras for angles up to 250deg 01490 Uses 6 cameras for angles up to 360deg 01491 */ 01492 int i; 01493 float deg45 = MT_PI / 4; 01494 MT_Scalar c = cos(deg45); 01495 MT_Scalar s = sin(deg45); 01496 01497 if (m_angle <= 180 && (m_mode == DOME_FISHEYE 01498 || m_mode == DOME_TRUNCATED_FRONT 01499 || m_mode == DOME_TRUNCATED_REAR)){ 01500 01501 m_locRot[0] = MT_Matrix3x3( // 90deg - Top 01502 c, -s, 0.0, 01503 0.0,0.0, -1.0, 01504 s, c, 0.0); 01505 01506 m_locRot[1] = MT_Matrix3x3( // 90deg - Bottom 01507 -s, c, 0.0, 01508 0.0,0.0, 1.0, 01509 s, c, 0.0); 01510 01511 m_locRot[2] = MT_Matrix3x3( // 45deg - Left 01512 c, 0.0, s, 01513 0, 1.0, 0.0, 01514 -s, 0.0, c); 01515 01516 m_locRot[3] = MT_Matrix3x3( // 45deg - Right 01517 c, 0.0, -s, 01518 0.0, 1.0, 0.0, 01519 s, 0.0, c); 01520 01521 } else if (m_mode == DOME_ENVMAP || (m_angle > 180 && (m_mode == DOME_FISHEYE 01522 || m_mode == DOME_TRUNCATED_FRONT 01523 || m_mode == DOME_TRUNCATED_REAR))){ 01524 01525 m_locRot[0] = MT_Matrix3x3( // 90deg - Top 01526 1.0, 0.0, 0.0, 01527 0.0, 0.0,-1.0, 01528 0.0, 1.0, 0.0); 01529 01530 m_locRot[1] = MT_Matrix3x3( // 90deg - Bottom 01531 1.0, 0.0, 0.0, 01532 0.0, 0.0, 1.0, 01533 0.0,-1.0, 0.0); 01534 01535 m_locRot[2] = MT_Matrix3x3( // -90deg - Left 01536 0.0, 0.0, 1.0, 01537 0.0, 1.0, 0.0, 01538 -1.0, 0.0, 0.0); 01539 01540 m_locRot[3] = MT_Matrix3x3( // 90deg - Right 01541 0.0, 0.0,-1.0, 01542 0.0, 1.0, 0.0, 01543 1.0, 0.0, 0.0); 01544 01545 m_locRot[4] = MT_Matrix3x3( // 0deg - Front 01546 1.0, 0.0, 0.0, 01547 0.0, 1.0, 0.0, 01548 0.0, 0.0, 1.0); 01549 01550 m_locRot[5] = MT_Matrix3x3( // 180deg - Back - USED for ENVMAP only 01551 -1.0, 0.0, 0.0, 01552 0.0, 1.0, 0.0, 01553 0.0, 0.0,-1.0); 01554 01555 } else if (m_mode == DOME_PANORAM_SPH){ 01556 01557 m_locRot[0] = MT_Matrix3x3( // Top 01558 c, s, 0.0, 01559 0.0,0.0, -1.0, 01560 -s, c, 0.0); 01561 01562 m_locRot[1] = MT_Matrix3x3( // Bottom 01563 c, s, 0.0, 01564 0.0 ,0.0, 1.0, 01565 s, -c, 0.0); 01566 01567 m_locRot[2] = MT_Matrix3x3( // 45deg - Left 01568 -s, 0.0, c, 01569 0, 1.0, 0.0, 01570 -c, 0.0, -s); 01571 01572 m_locRot[3] = MT_Matrix3x3( // 45deg - Right 01573 c, 0.0, s, 01574 0, 1.0, 0.0, 01575 -s, 0.0, c); 01576 01577 m_locRot[4] = MT_Matrix3x3( // 135deg - LeftBack 01578 -s, 0.0, -c, 01579 0.0, 1.0, 0.0, 01580 c, 0.0, -s); 01581 01582 m_locRot[5] = MT_Matrix3x3( // 135deg - RightBack 01583 c, 0.0, -s, 01584 0.0, 1.0, 0.0, 01585 s, 0.0, c); 01586 } 01587 01588 // rotating the camera in horizontal axis 01589 if (m_tilt) 01590 { 01591 float tiltdeg = ((m_tilt % 360) * 2 * MT_PI) / 360; 01592 c = cos(tiltdeg); 01593 s = sin(tiltdeg); 01594 01595 MT_Matrix3x3 tilt_mat = MT_Matrix3x3( 01596 1.0, 0.0, 0.0, 01597 0.0, c, -s, 01598 0.0, s, c 01599 ); 01600 01601 for (i =0;i<6;i++) 01602 m_locRot[i] = tilt_mat * m_locRot[i]; 01603 } 01604 } 01605 01606 void KX_Dome::RotateCamera(KX_Camera* cam, int i) 01607 { 01608 // I'm not using it, I'm doing inline calls for these commands 01609 // but it's nice to have it here in case I need it 01610 01611 MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation(); 01612 01613 cam->NodeSetLocalOrientation(camori*m_locRot[i]); 01614 cam->NodeUpdateGS(0.f); 01615 01616 MT_Transform camtrans(cam->GetWorldToCamera()); 01617 MT_Matrix4x4 viewmat(camtrans); 01618 m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective); 01619 cam->SetModelviewMatrix(viewmat); 01620 01621 // restore the original orientation 01622 cam->NodeSetLocalOrientation(camori); 01623 cam->NodeUpdateGS(0.f); 01624 } 01625 01626 void KX_Dome::Draw(void) 01627 { 01628 01629 if (fboSupported){ 01630 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId); 01631 01632 glViewport(0,0,warp.imagesize, warp.imagesize); 01633 glScissor(0,0,warp.imagesize, warp.imagesize); 01634 } 01635 01636 switch(m_mode){ 01637 case DOME_FISHEYE: 01638 DrawDomeFisheye(); 01639 break; 01640 case DOME_ENVMAP: 01641 DrawEnvMap(); 01642 break; 01643 case DOME_PANORAM_SPH: 01644 DrawPanorama(); 01645 break; 01646 case DOME_TRUNCATED_FRONT: 01647 DrawDomeFisheye(); 01648 break; 01649 case DOME_TRUNCATED_REAR: 01650 DrawDomeFisheye(); 01651 break; 01652 } 01653 01654 if(warp.usemesh) 01655 { 01656 if(fboSupported) 01657 { 01658 m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); 01659 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 01660 } 01661 else 01662 { 01663 glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); 01664 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight); 01665 } 01666 DrawDomeWarped(); 01667 } 01668 } 01669 01670 void KX_Dome::DrawEnvMap(void) 01671 { 01672 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01673 glMatrixMode(GL_PROJECTION); 01674 glLoadIdentity(); 01675 01676 // Making the viewport always square 01677 01678 int can_width = m_viewport.GetRight(); 01679 int can_height = m_viewport.GetTop(); 01680 01681 float ortho_width, ortho_height; 01682 01683 if (warp.usemesh) 01684 glOrtho((-1.0), 1.0, (-0.66), 0.66, -20.0, 10.0); //stretch the image to reduce resolution lost 01685 01686 else { 01687 if (can_width/3 <= can_height/2){ 01688 ortho_width = 1.0; 01689 ortho_height = (float)can_height/can_width; 01690 }else{ 01691 ortho_height = 2.0f / 3; 01692 ortho_width = (float)can_width/can_height * ortho_height; 01693 } 01694 01695 glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); 01696 } 01697 01698 glMatrixMode(GL_TEXTURE); 01699 glLoadIdentity(); 01700 glMatrixMode(GL_MODELVIEW); 01701 glLoadIdentity(); 01702 gluLookAt(0.0,0.0,1.0, 0.0,0.0,0.0, 0.0,1.0,0.0); 01703 01704 glPolygonMode(GL_FRONT, GL_FILL); 01705 glShadeModel(GL_SMOOTH); 01706 glDisable(GL_LIGHTING); 01707 glDisable(GL_DEPTH_TEST); 01708 01709 glEnable(GL_TEXTURE_2D); 01710 glColor3f(1.0,1.0,1.0); 01711 01712 float uv_ratio = (float)(m_buffersize-1) / m_imagesize; 01713 double onebythree = 1.0f / 3; 01714 01715 // domefacesId[0] => (top) 01716 glBindTexture(GL_TEXTURE_2D, domefacesId[0]); 01717 glBegin(GL_QUADS); 01718 glTexCoord2f(uv_ratio,uv_ratio); 01719 glVertex3f( onebythree, 0.0f, 3.0f); 01720 glTexCoord2f(0.0,uv_ratio); 01721 glVertex3f(-onebythree, 0.0f, 3.0f); 01722 glTexCoord2f(0.0,0.0); 01723 glVertex3f(-onebythree,-2 * onebythree, 3.0f); 01724 glTexCoord2f(uv_ratio,0.0); 01725 glVertex3f(onebythree,-2 * onebythree, 3.0f); 01726 glEnd(); 01727 01728 // domefacesId[1] => (bottom) 01729 glBindTexture(GL_TEXTURE_2D, domefacesId[1]); 01730 glBegin(GL_QUADS); 01731 glTexCoord2f(uv_ratio,uv_ratio); 01732 glVertex3f(-onebythree, 0.0f, 3.0f); 01733 glTexCoord2f(0.0,uv_ratio); 01734 glVertex3f(-1.0f, 0.0f, 3.0f); 01735 glTexCoord2f(0.0,0.0); 01736 glVertex3f(-1.0f,-2 * onebythree, 3.0f); 01737 glTexCoord2f(uv_ratio,0.0); 01738 glVertex3f(-onebythree,-2 * onebythree, 3.0f); 01739 glEnd(); 01740 01741 // domefacesId[2] => -90deg (left) 01742 glBindTexture(GL_TEXTURE_2D, domefacesId[2]); 01743 glBegin(GL_QUADS); 01744 glTexCoord2f(uv_ratio,uv_ratio); 01745 glVertex3f(-onebythree, 2 * onebythree, 3.0f); 01746 glTexCoord2f(0.0,uv_ratio); 01747 glVertex3f(-1.0f, 2 * onebythree, 3.0f); 01748 glTexCoord2f(0.0,0.0); 01749 glVertex3f(-1.0f, 0.0f, 3.0f); 01750 glTexCoord2f(uv_ratio,0.0); 01751 glVertex3f(-onebythree, 0.0f, 3.0f); 01752 glEnd(); 01753 01754 // domefacesId[3] => 90deg (right) 01755 glBindTexture(GL_TEXTURE_2D, domefacesId[3]); 01756 glBegin(GL_QUADS); 01757 glTexCoord2f(uv_ratio,uv_ratio); 01758 glVertex3f( 1.0f, 2 * onebythree, 3.0f); 01759 glTexCoord2f(0.0,uv_ratio); 01760 glVertex3f( onebythree, 2 * onebythree, 3.0f); 01761 glTexCoord2f(0.0,0.0); 01762 glVertex3f( onebythree, 0.0f, 3.0f); 01763 glTexCoord2f(uv_ratio,0.0); 01764 glVertex3f(1.0f, 0.0f, 3.0f); 01765 glEnd(); 01766 01767 // domefacesId[4] => 0deg (front) 01768 glBindTexture(GL_TEXTURE_2D, domefacesId[4]); 01769 glBegin(GL_QUADS); 01770 glTexCoord2f(uv_ratio,uv_ratio); 01771 glVertex3f( 1.0f, 0.0f, 3.0f); 01772 glTexCoord2f(0.0,uv_ratio); 01773 glVertex3f( onebythree, 0.0f, 3.0f); 01774 glTexCoord2f(0.0,0.0); 01775 glVertex3f( onebythree,-2 * onebythree, 3.0f); 01776 glTexCoord2f(uv_ratio,0.0); 01777 glVertex3f(1.0f, -2 * onebythree, 3.0f); 01778 glEnd(); 01779 01780 // domefacesId[5] => 180deg (back) 01781 glBindTexture(GL_TEXTURE_2D, domefacesId[5]); 01782 glBegin(GL_QUADS); 01783 glTexCoord2f(uv_ratio,uv_ratio); 01784 glVertex3f( onebythree, 2 * onebythree, 3.0f); 01785 glTexCoord2f(0.0,uv_ratio); 01786 glVertex3f(-onebythree, 2 * onebythree, 3.0f); 01787 glTexCoord2f(0.0,0.0); 01788 glVertex3f(-onebythree, 0.0f, 3.0f); 01789 glTexCoord2f(uv_ratio,0.0); 01790 glVertex3f(onebythree, 0.0f, 3.0f); 01791 glEnd(); 01792 01793 glDisable(GL_TEXTURE_2D); 01794 glEnable(GL_DEPTH_TEST); 01795 } 01796 01797 void KX_Dome::DrawDomeFisheye(void) 01798 { 01799 int i; 01800 01801 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01802 glMatrixMode(GL_PROJECTION); 01803 glLoadIdentity(); 01804 01805 // Making the viewport always square 01806 01807 int can_width = m_viewport.GetRight(); 01808 int can_height = m_viewport.GetTop(); 01809 01810 float ortho_width, ortho_height; 01811 01812 if(m_mode == DOME_FISHEYE) { 01813 if (warp.usemesh) 01814 glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost 01815 01816 else { 01817 if (can_width < can_height){ 01818 ortho_width = 1.0; 01819 ortho_height = (float)can_height/can_width; 01820 }else{ 01821 ortho_width = (float)can_width/can_height; 01822 ortho_height = 1.0; 01823 } 01824 01825 glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); 01826 } 01827 } 01828 else if(m_mode == DOME_TRUNCATED_FRONT) 01829 { 01830 ortho_width = 1.0; 01831 ortho_height = 2 * ((float)can_height/can_width) - 1.0 ; 01832 01833 glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0); 01834 } 01835 else { //m_mode == DOME_TRUNCATED_REAR 01836 ortho_width = 1.0; 01837 ortho_height = 2 * ((float)can_height/can_width) - 1.0 ; 01838 01839 glOrtho((-ortho_width), ortho_width, (-ortho_width), ortho_height, -20.0, 10.0); 01840 } 01841 01842 glMatrixMode(GL_TEXTURE); 01843 glLoadIdentity(); 01844 glMatrixMode(GL_MODELVIEW); 01845 glLoadIdentity(); 01846 gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0); 01847 01848 if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) 01849 glPolygonMode(GL_FRONT, GL_LINE); 01850 else 01851 glPolygonMode(GL_FRONT, GL_FILL); 01852 01853 glShadeModel(GL_SMOOTH); 01854 glDisable(GL_LIGHTING); 01855 glDisable(GL_DEPTH_TEST); 01856 01857 glEnable(GL_TEXTURE_2D); 01858 glColor3f(1.0,1.0,1.0); 01859 01860 if (dlistSupported){ 01861 for(i=0;i<m_numfaces;i++){ 01862 glBindTexture(GL_TEXTURE_2D, domefacesId[i]); 01863 glCallList(dlistId+i); 01864 } 01865 } 01866 else { // DisplayLists not supported 01867 // top triangle 01868 glBindTexture(GL_TEXTURE_2D, domefacesId[0]); 01869 GLDrawTriangles(cubetop, nfacestop); 01870 01871 // bottom triangle 01872 glBindTexture(GL_TEXTURE_2D, domefacesId[1]); 01873 GLDrawTriangles(cubebottom, nfacesbottom); 01874 01875 // left triangle 01876 glBindTexture(GL_TEXTURE_2D, domefacesId[2]); 01877 GLDrawTriangles(cubeleft, nfacesleft); 01878 01879 // right triangle 01880 glBindTexture(GL_TEXTURE_2D, domefacesId[3]); 01881 GLDrawTriangles(cuberight, nfacesright); 01882 01883 if (m_angle > 180){ 01884 // front triangle 01885 glBindTexture(GL_TEXTURE_2D, domefacesId[4]); 01886 GLDrawTriangles(cubefront, nfacesfront); 01887 } 01888 } 01889 glDisable(GL_TEXTURE_2D); 01890 glEnable(GL_DEPTH_TEST); 01891 } 01892 01893 void KX_Dome::DrawPanorama(void) 01894 { 01895 int i; 01896 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01897 glMatrixMode(GL_PROJECTION); 01898 glLoadIdentity(); 01899 01900 // Making the viewport always square 01901 01902 int can_width = m_viewport.GetRight(); 01903 int can_height = m_viewport.GetTop(); 01904 01905 float ortho_height = 1.0; 01906 float ortho_width = 1.0; 01907 01908 if (warp.usemesh) 01909 glOrtho((-1.0), 1.0, (-0.5), 0.5, -20.0, 10.0); //stretch the image to reduce resolution lost 01910 01911 else { 01912 //using all the screen 01913 if ((can_width / 2) <= (can_height)){ 01914 ortho_width = 1.0; 01915 ortho_height = (float)can_height/can_width; 01916 }else{ 01917 ortho_width = (float)can_width/can_height * 0.5; 01918 ortho_height = 0.5; 01919 } 01920 01921 glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); 01922 } 01923 01924 glMatrixMode(GL_TEXTURE); 01925 glLoadIdentity(); 01926 glMatrixMode(GL_MODELVIEW); 01927 glLoadIdentity(); 01928 gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0); 01929 01930 if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) 01931 glPolygonMode(GL_FRONT, GL_LINE); 01932 else 01933 glPolygonMode(GL_FRONT, GL_FILL); 01934 01935 glShadeModel(GL_SMOOTH); 01936 glDisable(GL_LIGHTING); 01937 glDisable(GL_DEPTH_TEST); 01938 01939 glEnable(GL_TEXTURE_2D); 01940 glColor3f(1.0,1.0,1.0); 01941 01942 if (dlistSupported){ 01943 for(i=0;i<m_numfaces;i++){ 01944 glBindTexture(GL_TEXTURE_2D, domefacesId[i]); 01945 glCallList(dlistId+i); 01946 } 01947 } 01948 else { 01949 // domefacesId[4] => (top) 01950 glBindTexture(GL_TEXTURE_2D, domefacesId[0]); 01951 GLDrawTriangles(cubetop, nfacestop); 01952 01953 // domefacesId[5] => (bottom) 01954 glBindTexture(GL_TEXTURE_2D, domefacesId[1]); 01955 GLDrawTriangles(cubebottom, nfacesbottom); 01956 01957 // domefacesId[1] => -45deg (left) 01958 glBindTexture(GL_TEXTURE_2D, domefacesId[2]); 01959 GLDrawTriangles(cubeleft, nfacesleft); 01960 01961 // domefacesId[2] => 45deg (right) 01962 glBindTexture(GL_TEXTURE_2D, domefacesId[3]); 01963 GLDrawTriangles(cuberight, nfacesright); 01964 01965 // domefacesId[0] => -135deg (leftback) 01966 glBindTexture(GL_TEXTURE_2D, domefacesId[4]); 01967 GLDrawTriangles(cubeleftback, nfacesleftback); 01968 01969 // domefacesId[3] => 135deg (rightback) 01970 glBindTexture(GL_TEXTURE_2D, domefacesId[5]); 01971 GLDrawTriangles(cuberightback, nfacesrightback); 01972 } 01973 glDisable(GL_TEXTURE_2D); 01974 glEnable(GL_DEPTH_TEST); 01975 } 01976 01977 void KX_Dome::DrawDomeWarped(void) 01978 { 01979 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01980 glMatrixMode(GL_PROJECTION); 01981 glLoadIdentity(); 01982 01983 // Making the viewport always square 01984 int can_width = m_viewport.GetRight(); 01985 int can_height = m_viewport.GetTop(); 01986 01987 double screen_ratio = can_width/ (double) can_height; 01988 01989 glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0); 01990 01991 01992 glMatrixMode(GL_TEXTURE); 01993 glLoadIdentity(); 01994 glMatrixMode(GL_MODELVIEW); 01995 glLoadIdentity(); 01996 gluLookAt(0.0, 0.0, 1.0, 0.0,0.0,0.0, 0.0,1.0,0.0); 01997 01998 if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) 01999 glPolygonMode(GL_FRONT, GL_LINE); 02000 else 02001 glPolygonMode(GL_FRONT, GL_FILL); 02002 02003 glShadeModel(GL_SMOOTH); 02004 glDisable(GL_LIGHTING); 02005 glDisable(GL_DEPTH_TEST); 02006 02007 glEnable(GL_TEXTURE_2D); 02008 glColor3f(1.0,1.0,1.0); 02009 02010 if (dlistSupported){ 02011 glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); 02012 glCallList(dlistId + m_numfaces); 02013 } 02014 else{ 02015 glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); 02016 GLDrawWarpQuads(); 02017 } 02018 glDisable(GL_TEXTURE_2D); 02019 glEnable(GL_DEPTH_TEST); 02020 } 02021 02022 void KX_Dome::BindImages(int i) 02023 { 02024 glBindTexture(GL_TEXTURE_2D, domefacesId[i]); 02025 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), m_buffersize, m_buffersize); 02026 } 02027 02028 void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i) 02029 { 02030 if (!cam) 02031 return; 02032 02033 m_canvas->SetViewPort(0,0,m_buffersize-1,m_buffersize-1); 02034 02035 // m_rasterizer->SetAmbient(); 02036 m_rasterizer->DisplayFog(); 02037 02038 CalculateFrustum(cam); //calculates m_projmat 02039 cam->SetProjectionMatrix(m_projmat); 02040 m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix()); 02041 // Dome_RotateCamera(cam,i); 02042 02043 MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation(); 02044 02045 cam->NodeSetLocalOrientation(camori*m_locRot[i]); 02046 cam->NodeUpdateGS(0.f); 02047 02048 MT_Transform camtrans(cam->GetWorldToCamera()); 02049 MT_Matrix4x4 viewmat(camtrans); 02050 m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), 1.0); 02051 cam->SetModelviewMatrix(viewmat); 02052 02053 // restore the original orientation 02054 cam->NodeSetLocalOrientation(camori); 02055 cam->NodeUpdateGS(0.f); 02056 02057 scene->CalculateVisibleMeshes(m_rasterizer,cam); 02058 scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); 02059 } 02060