Blender V2.61 - r43446

KX_Dome.cpp

Go to the documentation of this file.
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