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