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