Patch #18462: Fisheye (Dome) and Spherical Panoramic mode in BGE.
authorBenoit Bolsee <benoit.bolsee@online.be>
Wed, 8 Apr 2009 15:06:20 +0000 (15:06 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Wed, 8 Apr 2009 15:06:20 +0000 (15:06 +0000)
User guide:
http://wiki.blender.org/index.php/Dev:Source/GameEngine/Fisheye_Dome_Camera

Fixed two bugs from original patch:
- deleting a text will clear the warp field from Game framing settings
- removed spurious black dots along the edge of the cube map in the gameplayer

Known limitation:
- resizing of the screen doesn't work in the gameplayer

Known bugs:
- Texture with reflexion are not rendered correctly
- Spurious problems with light

16 files changed:
projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_scene_types.h
source/blender/src/buttons_scene.c
source/blender/src/header_text.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/Ketsji/KX_Dome.cpp [new file with mode: 0644]
source/gameengine/Ketsji/KX_Dome.h [new file with mode: 0644]
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_KetsjiEngine.h
source/gameengine/Rasterizer/RAS_IRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp

index c425b5664ad4baa39501a5cac8247057d18bf180..80c34bef2238cc847cfdc28aa2de7871644ce586 100644 (file)
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_ConvertPhysicsObjects.cpp"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\..\source\gameengine\Ketsji\KX_Dome.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_EmptyObject.cpp"\r
                                >\r
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_ConvertPhysicsObject.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\..\source\gameengine\Ketsji\KX_Dome.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_EmptyObject.h"\r
                                >\r
index db6d4762b17f7a01a6a33e65e2c1e7461eedca05..d49a5425b61f0049a05498fbce19721870ef0a60 100644 (file)
@@ -41,7 +41,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        248
-#define BLENDER_SUBVERSION             3
+#define BLENDER_SUBVERSION             4
 
 #define BLENDER_MINVERSION             245
 #define BLENDER_MINSUBVERSION  15
index 2bd528ab8c8abc0ddd167a43a3a0f1a9690e9e7a..2c3ef42c02114e6985a4c3639ee689be430247c9 100644 (file)
@@ -86,5 +86,7 @@ int get_render_child_particle_number(struct RenderData *r, int num);
 int get_render_shadow_samples(struct RenderData *r, int samples);
 float get_render_aosss_error(struct RenderData *r, float error);
 
+void free_dome_warp_text(struct Text *txt);
+
 #endif
 
index 1727edc10fce3735c32401c34952683b1a500fe5..5def3577218b89ca256f860fcfb84cf987e89008 100644 (file)
@@ -230,6 +230,11 @@ Scene *add_scene(char *name)
        sce->r.threads= 1;
        
        sce->r.stereomode = 1;  // no stereo
+       sce->r.domeangle = 180;
+       sce->r.domemode = 1;
+       sce->r.domesize = 1.0f;
+       sce->r.domeres = 4;
+       sce->r.domeresbuf = 1.0f;
 
        sce->r.simplify_subsurf= 6;
        sce->r.simplify_particles= 1.0f;
@@ -775,3 +780,14 @@ float get_render_aosss_error(RenderData *r, float error)
                return error;
 }
 
+void free_dome_warp_text(struct Text *txt)
+{
+       Scene *scene;
+
+       scene = G.main->scene.first;
+       while(scene) {
+               if (scene->r.dometext == txt)
+                       scene->r.dometext = NULL;
+               scene = scene->id.next;
+       }
+}
\ No newline at end of file
index c2eaae011c87d59dcf1c1ca4a7c87a93770d45ff..06c8370bde2d48b7d968d150d07c0409fdd8a3ab 100644 (file)
@@ -3531,7 +3531,9 @@ static void lib_link_scene(FileData *fd, Main *main)
                                srl->mat_override= newlibadr_us(fd, sce->id.lib, srl->mat_override);
                                srl->light_override= newlibadr_us(fd, sce->id.lib, srl->light_override);
                        }
-                       
+                       /*Game Settings: Dome Warp Text*/
+                       sce->r.dometext= newlibadr_us(fd, sce->id.lib, sce->r.dometext);
+
                        sce->id.flag -= LIB_NEEDLINK;
                }
 
@@ -8035,6 +8037,24 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
        
+       if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 4)) {
+               Scene *sce;
+               World *wrld;
+
+               /*  Dome (Fisheye) default parameters  */
+               for (sce= main->scene.first; sce; sce= sce->id.next) {
+                       sce->r.domeangle = 180;
+                       sce->r.domemode = 1;
+                       sce->r.domesize = 1.0f;
+                       sce->r.domeres = 4;
+                       sce->r.domeresbuf = 1.0f;
+               }
+               /* DBVT culling by default */
+               for(wrld=main->world.first; wrld; wrld= wrld->id.next) {
+                       wrld->mode |= WO_DBVT_CAMERA_CULLING;
+               }
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
 
@@ -8841,7 +8861,9 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
                expand_doit(fd, mainvar, srl->mat_override);
                expand_doit(fd, mainvar, srl->light_override);
        }
-                               
+
+       if(sce->r.dometext)
+               expand_doit(fd, mainvar, sce->r.dometext);
 }
 
 static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
index b8a734b6e941ffa5b7a616b29784b26626e3c762..bf5b2ad3df54e048c1710c975f673727d665be4f 100644 (file)
@@ -45,6 +45,7 @@ struct World;
 struct Scene;
 struct Image;
 struct Group;
+struct Text;
 struct bNodeTree;
 
 typedef struct Base {
@@ -314,6 +315,14 @@ typedef struct RenderData {
        /* jpeg2000 */
        short jp2_preset, jp2_depth;
        int rpad3;
+
+       /* Dome variables */
+       short domeres, domemode;
+       short domeangle, pad9;
+       float domesize;
+       float domeresbuf;
+       struct Text *dometext;
+
 } RenderData;
 
 /* control render convert and shading engine */
index aa072285556b6600ef6b3bd7754046d3c46db54c..f026e5f4034cc9fb52885e74332a9c7662e0ae16 100644 (file)
@@ -1766,13 +1766,13 @@ static uiBlock *edge_render_menu(void *arg_unused)
 static uiBlock *framing_render_menu(void *arg_unused)
 {
        uiBlock *block;
-       short yco = 190, xco = 0;
+       short yco = 267, xco = 0;
        int randomcolorindex = 1234;
 
        block= uiNewBlock(&curarea->uiblocks, "framing_options", UI_EMBOSS, UI_HELV, curarea->win);
 
        /* use this for a fake extra empy space around the buttons */
-       uiDefBut(block, LABEL, 0, "",                   -5, -10, 295, 224, NULL, 0, 0, 0, 0, "");
+       uiDefBut(block, LABEL, 0, "",                   -5, -10, 295, 300, NULL, 0, 0, 0, 0, "");
 
        uiDefBut(block, LABEL, 0, "Framing:", xco, yco, 68,19, 0, 0, 0, 0, 0, "");
        uiBlockBeginAlign(block);
@@ -1814,6 +1814,7 @@ static uiBlock *framing_render_menu(void *arg_unused)
         * RAS_STEREO_ANAGLYPH          5
         * RAS_STEREO_SIDEBYSIDE        6
         * RAS_STEREO_VINTERLACE        7
+        * RAS_STEREO_DOME              8
         */
        uiBlockBeginAlign(block);
        uiDefButS(block, ROW, 0, "No Stereo", xco, yco-=30, 88, 19, &(G.scene->r.stereomode), 7.0, 1.0, 0, 0, "Disables stereo");
@@ -1825,6 +1826,18 @@ static uiBlock *framing_render_menu(void *arg_unused)
        
        uiBlockEndAlign(block);
 
+       uiBlockBeginAlign(block);
+       uiDefButS(block, ROW, 0, "Dome", xco-=180, yco-=30, 88, 19, &(G.scene->r.stereomode), 7.0, 8.0, 0, 0, "Enables dome camera");
+       uiDefButS(block, NUM, 0, "Ang:",                xco+=90, yco, 88, 19, &G.scene->r.domeangle, 90.0, 250.0, 0, 0, "Angle (Aperture) of the Dome - it only works in mode 1");
+       uiDefButS(block, NUM, 0, "Mode:",               xco+=90, yco, 88, 19, &G.scene->r.domemode, 1.0, 3.0, 0, 0, "Dome mode - 1 fisheye, 2 truncated, 3 spherical panoramic");
+
+       uiDefButF(block, NUM, 0, "Size:",               xco-=180, yco-=21, 88, 19, &G.scene->r.domesize, 0.5, 3.5, 0, 0, "Size adjustments");
+       uiDefButS(block, NUM, 0, "Tes:",                xco+=90, yco, 88, 19, &G.scene->r.domeres, 1.0, 8.0, 0, 0, "Tesselation level - 1 to 8");
+       uiDefButF(block, NUM, 0, "Res:",        xco+=90, yco, 88, 19, &G.scene->r.domeresbuf, 0.1, 1.0, 0, 0, "Buffer Resolution - decrease it to increase speed");
+
+       uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Warp Data: ", xco-180,yco-=21,268, 19, &G.scene->r.dometext, "Custom Warp Mesh data file");
+       uiBlockEndAlign(block);
+
        uiBlockSetDirection(block, UI_TOP);
 
        return block;
index 9268642db2f722c4c28e3b021624a4fd3ffa53e4..050ff192df60714c69ee9b0abeed89fa98f54e62 100644 (file)
@@ -173,6 +173,7 @@ void do_text_buttons(unsigned short event)
                        BPY_clear_bad_scriptlinks(text);
                        BPY_free_pyconstraint_links(text);
                        free_text_controllers(text);
+                       free_dome_warp_text(text);
 #endif
                        unlink_text(text);
                        free_libblock(&G.main->text, text);
index 1c91ad784acb3eaa789d71fe725ebbd0d90d5990..fee5a4ad899e6bd7bede7215209619db39132b62 100644 (file)
@@ -373,6 +373,10 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
                        initVideoTexture();
 #endif
 
+                       //initialize Dome Settings
+                       if(blscene->r.stereomode == RAS_IRasterizer::RAS_STEREO_DOME)
+                               ketsjiengine->InitDome(blscene->r.domesize, blscene->r.domeres, blscene->r.domemode, blscene->r.domeangle, blscene->r.domeresbuf, blscene->r.dometext);
+
                        if (sceneconverter)
                        {
                                // convert and add scene
index 3432d49898153670eb5adef8d2e6f3eb18e4a042..6ff46ca82008f2b75a8b7bd407dc92cd3fd9acc5 100644 (file)
@@ -693,6 +693,11 @@ bool GPG_Application::startEngine(void)
 #ifdef WITH_FFMPEG
         initVideoTexture();
 #endif
+
+               //initialize Dome Settings
+               if(m_startScene->r.stereomode == RAS_IRasterizer::RAS_STEREO_DOME)
+                       m_ketsjiengine->InitDome(m_startScene->r.domesize, m_startScene->r.domeres, m_startScene->r.domemode, m_startScene->r.domeangle, m_startScene->r.domeresbuf, m_startScene->r.dometext);
+
                // Set the GameLogic.globalDict from marshal'd data, so we can
                // load new blend files and keep data in GameLogic.globalDict
                loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length);
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
new file mode 100644 (file)
index 0000000..4ab0f93
--- /dev/null
@@ -0,0 +1,1820 @@
+/* $Id$
+-----------------------------------------------------------------------------
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+
+Contributor(s): Dalai Felinto
+
+This code is originally inspired on some of the ideas and codes from Paul Bourke.
+Developed as part of a Research and Development project for SAT - La Société des arts technologiques.
+-----------------------------------------------------------------------------
+*/
+
+#include "KX_Dome.h"
+
+#include <structmember.h>
+#include <float.h>
+#include <math.h>
+
+#include "DNA_scene_types.h"
+#include "RAS_CameraData.h"
+#include "BLI_arithb.h"
+
+#include "GL/glew.h"
+#include "GL/glu.h"
+
+// constructor
+KX_Dome::KX_Dome (
+       RAS_ICanvas* canvas,
+    /// rasterizer
+    RAS_IRasterizer* rasterizer,
+    /// render tools
+    RAS_IRenderTools* rendertools,
+    /// engine
+    KX_KetsjiEngine* engine,
+       
+       float size,             //size for adjustments
+       short res,              //resolution of the mesh
+       short mode,             //mode - fisheye, truncated, warped, panoramic, ...
+       short angle,
+       float resbuf,   //size adjustment of the buffer
+       struct Text* warptext
+
+):
+       m_canvas(canvas),
+       m_rasterizer(rasterizer),
+       m_rendertools(rendertools),
+       m_engine(engine),
+       m_drawingmode(engine->GetDrawType()),
+       m_size(size),
+       m_resolution(res),
+       m_mode(mode),
+       m_angle(angle),
+       m_resbuffer(resbuf),
+       canvaswidth(-1), canvasheight(-1),
+       dlistSupported(false)
+{
+       warp.usemesh = false;
+
+       if (mode >= DOME_NUM_MODES)
+               m_mode = DOME_FISHEYE;
+
+       if (warptext) // it there is a text data try to warp it
+       {
+               char *buf;
+               buf = txt_to_buf(warptext);
+               if (buf)
+               {
+                       warp.usemesh = ParseWarpMesh(STR_String(buf));
+                       MEM_freeN(buf);
+               }
+       }
+
+       //setting the viewport size
+       GLuint  viewport[4]={0};
+       glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
+
+       SetViewPort(viewport);
+
+       switch(m_mode){
+               case DOME_FISHEYE:
+                       if (m_angle <= 180){
+                               cubetop.resize(1);
+                               cubebottom.resize(1);
+                               cubeleft.resize(2);
+                               cuberight.resize(2);
+
+                               CreateMeshDome180();
+                               m_numfaces = 4;
+                       }else if (m_angle > 180){
+                               cubetop.resize(2);
+                               cubebottom.resize(2);
+                               cubeleft.resize(2);
+                               cubefront.resize(2);
+                               cuberight.resize(2);
+
+                               CreateMeshDome250();
+                               m_numfaces = 5;
+                       } break;
+               case DOME_TRUNCATED:
+                       cubetop.resize(1);
+                       cubebottom.resize(1);
+                       cubeleft.resize(2);
+                       cuberight.resize(2);
+
+                       m_angle = 180;
+                       CreateMeshDome180();
+                       m_numfaces = 4;
+                       break;
+               case DOME_PANORAM_SPH:
+                       cubeleft.resize(2);
+                       cubeleftback.resize(2);
+                       cuberight.resize(2);
+                       cuberightback.resize(2);
+                       cubetop.resize(2);
+                       cubebottom.resize(2);
+
+                       m_angle = 360;
+                       CreateMeshPanorama();
+                       m_numfaces = 6;
+                       break;
+       }
+
+       m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces);
+
+       CalculateCameraOrientation();
+
+       CreateGLImages();
+
+       dlistSupported = CreateDL();
+}
+
+// destructor
+KX_Dome::~KX_Dome (void)
+{
+       GLuint m_numimages = m_numfaces;
+
+       ClearGLImages();
+
+       if(dlistSupported)
+               glDeleteLists(dlistId, (GLsizei) m_numimages);
+}
+
+void KX_Dome::SetViewPort(GLuint viewport[4])
+{
+       if(canvaswidth != m_canvas->GetWidth() || canvasheight != m_canvas->GetHeight())
+       {
+               m_viewport.SetLeft(viewport[0]); 
+               m_viewport.SetBottom(viewport[1]);
+               m_viewport.SetRight(viewport[2]);
+               m_viewport.SetTop(viewport[3]);
+
+               CalculateImageSize();
+       }
+}
+
+void KX_Dome::CreateGLImages(void)
+{
+       glGenTextures(m_numimages, (GLuint*)&domefacesId);
+
+       for (int j=0;j<m_numfaces;j++){
+               glBindTexture(GL_TEXTURE_2D, domefacesId[j]);
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_imagesize, m_imagesize, 0, GL_RGB8,
+                               GL_UNSIGNED_BYTE, 0);
+               glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, m_imagesize, m_imagesize, 0);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       }
+       if(warp.usemesh){
+               glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagewidth, warp.imageheight, 0, GL_RGB8,
+                               GL_UNSIGNED_BYTE, 0);
+               glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagewidth, warp.imageheight, 0);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       }
+}
+
+void KX_Dome::ClearGLImages(void)
+{
+       glDeleteTextures(m_numimages, (GLuint*)&domefacesId);
+/*
+       for (int i=0;i<m_numimages;i++)
+               if(glIsTexture(domefacesId[i]))
+                       glDeleteTextures(1, (GLuint*)&domefacesId[i]);
+*/
+}
+
+void KX_Dome::CalculateImageSize(void)
+{
+/*
+- determine the minimum buffer size
+- reduce the buffer for better performace
+- create a power of 2 texture bigger than the buffer
+*/
+
+       canvaswidth = m_canvas->GetWidth();
+       canvasheight = m_canvas->GetHeight();
+
+       m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth);
+       m_buffersize *= m_resbuffer; //reduce buffer size for better performance
+
+       int i = 0;
+       while ((1 << i) <= m_buffersize)
+               i++;
+       m_imagesize = (1 << i);
+
+       if (warp.usemesh){
+               warp.bufferwidth = canvaswidth;
+               warp.bufferheight = canvasheight;
+
+               i = 0;
+               while ((1 << i) <= warp.bufferwidth)
+                       i++;
+               warp.imagewidth = (1 << i);
+
+               i = 0;
+               while ((1 << i) <= warp.bufferheight)
+                       i++;
+               warp.imageheight = (1 << i);
+       }
+}
+
+bool KX_Dome::CreateDL(){
+       int i,j;
+
+       dlistId = glGenLists((GLsizei) m_numimages);
+       if (dlistId != 0) {
+               if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED){
+                       glNewList(dlistId, GL_COMPILE);
+                               GLDrawTriangles(cubetop, nfacestop);
+                       glEndList();
+
+                       glNewList(dlistId+1, GL_COMPILE);
+                               GLDrawTriangles(cubebottom, nfacesbottom);
+                       glEndList();
+
+                       glNewList(dlistId+2, GL_COMPILE);
+                               GLDrawTriangles(cubeleft, nfacesleft);
+                       glEndList();
+
+                       glNewList(dlistId+3, GL_COMPILE);
+                               GLDrawTriangles(cuberight, nfacesright);
+                       glEndList();
+
+                       if (m_angle > 180){
+                               glNewList(dlistId+4, GL_COMPILE);
+                                       GLDrawTriangles(cubefront, nfacesfront);
+                               glEndList();
+                       }
+               }
+               else if (m_mode == DOME_PANORAM_SPH)
+               {
+                       glNewList(dlistId, GL_COMPILE);
+                               GLDrawTriangles(cubetop, nfacestop);
+                       glEndList();
+
+                       glNewList(dlistId+1, GL_COMPILE);
+                               GLDrawTriangles(cubebottom, nfacesbottom);
+                       glEndList();
+
+                       glNewList(dlistId+2, GL_COMPILE);
+                               GLDrawTriangles(cubeleft, nfacesleft);
+                       glEndList();
+
+                       glNewList(dlistId+3, GL_COMPILE);
+                               GLDrawTriangles(cuberight, nfacesright);
+                       glEndList();
+
+                       glNewList(dlistId+4, GL_COMPILE);
+                               GLDrawTriangles(cubeleftback, nfacesleftback);
+                       glEndList();
+
+                       glNewList(dlistId+5, GL_COMPILE);
+                               GLDrawTriangles(cuberightback, nfacesrightback);
+                       glEndList();
+               }
+
+               if(warp.usemesh){
+                       glNewList((dlistId + m_numfaces), GL_COMPILE);
+                               GLDrawWarpQuads();
+                       glEndList();
+               }
+
+               //clearing the vectors 
+               cubetop.clear();
+               cubebottom.clear();
+               cuberight.clear();
+               cubeleft.clear();
+               cubefront.clear();
+               cubeleftback.clear();
+               cuberightback.clear();
+               warp.nodes.clear();
+
+       } else // genList failed
+               return false;
+
+       return true;
+}
+
+void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces)
+{
+       int i,j;
+       glBegin(GL_TRIANGLES);
+               for (i=0;i<nfaces;i++) {
+                       for (j=0;j<3;j++) {
+                               glTexCoord2f(face[i].u[j],face[i].v[j]);
+                               glVertex3f((GLfloat)face[i].verts[j][0],(GLfloat)face[i].verts[j][1],(GLfloat)face[i].verts[j][2]);
+                       }
+               }
+       glEnd();
+}
+
+void KX_Dome::GLDrawWarpQuads(void)
+{
+       int i, j, i2;
+       float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth;
+       float uv_height = (float)(warp.bufferheight-1) / warp.imageheight;
+
+       if(warp.mode ==2 ){
+               glBegin(GL_QUADS);
+               for (i=0;i<warp.n_height-1;i++) {
+                       for (j=0;j<warp.n_width-1;j++) {
+                               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)
+                                       continue;
+
+                               glColor3f(warp.nodes[i][j].i, warp.nodes[i][j].i, warp.nodes[i][j].i);
+                               glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height));
+                               glVertex3f(warp.nodes[i][j].x, warp.nodes[i][j].y,0.0);
+
+                               glColor3f(warp.nodes[i+1][j].i, warp.nodes[i+1][j].i, warp.nodes[i+1][j].i);
+                               glTexCoord2f((warp.nodes[i+1][j].u * uv_width), (warp.nodes[i+1][j].v * uv_height));
+                               glVertex3f(warp.nodes[i+1][j].x, warp.nodes[i+1][j].y,0.0);
+
+                               glColor3f(warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i);
+                               glTexCoord2f((warp.nodes[i+1][j+1].u * uv_width), (warp.nodes[i+1][j+1].v * uv_height));
+                               glVertex3f(warp.nodes[i+1][j+1].x, warp.nodes[i+1][j+1].y,0.0);
+
+                               glColor3f(warp.nodes[i][j+1].i, warp.nodes[i][j+1].i, warp.nodes[i][j+1].i);
+                               glTexCoord2f((warp.nodes[i][j+1].u * uv_width), (warp.nodes[i][j+1].v * uv_height));
+                               glVertex3f(warp.nodes[i][j+1].x, warp.nodes[i][j+1].y,0.0);
+                       }
+               }
+               glEnd();
+       }
+       else if (warp.mode == 1){
+               glBegin(GL_QUADS);
+               for (i=0;i<warp.n_height-1;i++) {
+                       for (j=0;j<warp.n_width-1;j++) {
+                               i2 = (i+1) % warp.n_width; // Wrap around, i = warp.n_width = 0
+
+                               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)
+                                       continue;
+
+                                glColor3f(warp.nodes[i][j].i,warp.nodes[i][j].i,warp.nodes[i][j].i);
+                                glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height));
+                                glVertex3f(warp.nodes[i][j].x,warp.nodes[i][j].y,0.0);
+
+                                glColor3f(warp.nodes[i2][j].i,warp.nodes[i2][j].i,warp.nodes[i2][j].i);
+                                glTexCoord2f((warp.nodes[i2][j].u * uv_width), (warp.nodes[i2][j].v * uv_height));
+                                glVertex3f(warp.nodes[i2][j].x,warp.nodes[i2][j].y,0.0);
+
+                                glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i);
+                                glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height));
+                                glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0);
+
+                                glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i);
+                                glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height));
+                                glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0);
+
+                       }
+               }
+               glEnd();
+       } else{
+               printf("Error: Warp Mode unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n");
+       }
+}
+
+
+bool KX_Dome::ParseWarpMesh(STR_String text)
+{
+/*
+//Notes about the supported data format:
+File example::
+       mode
+       width height
+       n0_x n0_y n0_u n0_v n0_i
+       n1_x n1_y n1_u n1_v n1_i
+       n2_x n1_y n2_u n2_v n2_i
+       n3_x n3_y n3_u n3_v n3_i
+       (...)
+First line is the image type the mesh is support to be applied to: 2 = fisheye, 1=radial
+Tthe next line has the mesh dimensions
+Rest of the lines are the nodes of the mesh. Each line has x y u v i
+  (x,y) are the normalised screen coordinates
+  (u,v) texture coordinates
+  i a multiplicative intensity factor
+
+x varies from -screen aspect to screen aspect
+y varies from -1 to 1
+u and v vary from 0 to 1
+i ranges from 0 to 1, if negative don't draw that mesh node
+*/
+       int i,j,k;
+       int nodeX=0, nodeY=0;
+
+       vector<STR_String> columns, lines;
+
+       lines = text.Explode('\n');
+       if(lines.size() < 6){
+               printf("Error: Warp Mesh File with insufficient data!\n");
+               return false;
+       }
+       columns = lines[1].Explode(' ');
+
+       if(columns.size() !=2){
+               printf("Error: Warp Mesh File incorrect. The second line should contain: width height.\n");
+               return false;
+       }
+
+       warp.mode = atoi(lines[0]);// 1 = radial, 2 = fisheye
+
+       warp.n_width = atoi(columns[0]);
+       warp.n_height = atoi(columns[1]);
+
+       if (lines.size() < 2 + (warp.n_width * warp.n_height)){
+               printf("Error: Warp Mesh File with insufficient data!\n");
+               return false;
+       }else{
+               warp.nodes = vector<vector <WarpMeshNode>> (warp.n_height, vector<WarpMeshNode>(warp.n_width));
+
+               for(i=2; i-2 < (warp.n_width*warp.n_height); i++){
+                       columns = lines[i].Explode(' ');
+
+                       if (columns.size() == 5){
+                               nodeX = (i-2)%warp.n_width;
+                               nodeY = ((i-2) - nodeX) / warp.n_width;
+
+                               warp.nodes[nodeY][nodeX].x = atof(columns[0]);
+                               warp.nodes[nodeY][nodeX].y = atof(columns[1]);
+                               warp.nodes[nodeY][nodeX].u = atof(columns[2]);
+                               warp.nodes[nodeY][nodeX].v = atof(columns[3]);
+                               warp.nodes[nodeY][nodeX].i = atof(columns[4]);
+                       }
+                       else{
+                               warp.nodes.clear();
+                               printf("Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n");
+                               return false;
+                       }
+               }
+       }
+       return true;
+}
+
+void KX_Dome::CreateMeshDome180(void)
+{
+/*
+1)-  Define the faces of half of a cube 
+ - each face is made out of 2 triangles
+2) Subdivide the faces
+ - more resolution == more curved lines
+3) Spherize the cube
+ - normalize the verts
+4) Flatten onto xz plane
+ - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image
+*/
+       int i,j;
+       float sqrt_2 = sqrt(2.0);
+       float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
+
+       m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening
+
+       //creating faces for the env mapcube 180º Dome
+       // Top Face - just a triangle
+       cubetop[0].verts[0][0] = -sqrt_2 / 2.0;
+       cubetop[0].verts[0][1] = 0.0;
+       cubetop[0].verts[0][2] = 0.5;
+       cubetop[0].u[0] = 0.0;
+       cubetop[0].v[0] = uv_ratio;
+
+       cubetop[0].verts[1][0] = 0.0;
+       cubetop[0].verts[1][1] = sqrt_2 / 2.0;
+       cubetop[0].verts[1][2] = 0.5;
+       cubetop[0].u[1] = 0.0;
+       cubetop[0].v[1] = 0.0;
+
+       cubetop[0].verts[2][0] = sqrt_2 / 2.0;
+       cubetop[0].verts[2][1] = 0.0;
+       cubetop[0].verts[2][2] = 0.5;
+       cubetop[0].u[2] = uv_ratio;
+       cubetop[0].v[2] = 0.0;
+
+       nfacestop = 1;
+
+       /* Bottom face - just a triangle */
+       cubebottom[0].verts[0][0] = -sqrt_2 / 2.0;
+       cubebottom[0].verts[0][1] = 0.0;
+       cubebottom[0].verts[0][2] = -0.5;
+       cubebottom[0].u[0] = uv_ratio;
+       cubebottom[0].v[0] = 0.0;
+
+       cubebottom[0].verts[1][0] = sqrt_2 / 2.0;
+       cubebottom[0].verts[1][1] = 0;
+       cubebottom[0].verts[1][2] = -0.5;
+       cubebottom[0].u[1] = 0.0;
+       cubebottom[0].v[1] = uv_ratio;
+
+       cubebottom[0].verts[2][0] = 0.0;
+       cubebottom[0].verts[2][1] = sqrt_2 / 2.0;
+       cubebottom[0].verts[2][2] = -0.5;
+       cubebottom[0].u[2] = 0.0;
+       cubebottom[0].v[2] = 0.0;
+
+       nfacesbottom = 1;       
+       
+       /* Left face - two triangles */
+       
+       cubeleft[0].verts[0][0] = -sqrt_2 / 2.0;
+       cubeleft[0].verts[0][1] = .0;
+       cubeleft[0].verts[0][2] = -0.5;
+       cubeleft[0].u[0] = 0.0;
+       cubeleft[0].v[0] = 0.0;
+
+       cubeleft[0].verts[1][0] = 0.0;
+       cubeleft[0].verts[1][1] = sqrt_2 / 2.0;
+       cubeleft[0].verts[1][2] = -0.5;
+       cubeleft[0].u[1] = uv_ratio;
+       cubeleft[0].v[1] = 0.0;
+
+       cubeleft[0].verts[2][0] = -sqrt_2 / 2.0;
+       cubeleft[0].verts[2][1] = 0.0;
+       cubeleft[0].verts[2][2] = 0.5;
+       cubeleft[0].u[2] = 0.0;
+       cubeleft[0].v[2] = uv_ratio;
+
+       //second triangle
+       cubeleft[1].verts[0][0] = -sqrt_2 / 2.0;
+       cubeleft[1].verts[0][1] = 0.0;
+       cubeleft[1].verts[0][2] = 0.5;
+       cubeleft[1].u[0] = 0.0;
+       cubeleft[1].v[0] = uv_ratio;
+
+       cubeleft[1].verts[1][0] = 0.0;
+       cubeleft[1].verts[1][1] = sqrt_2 / 2.0;
+       cubeleft[1].verts[1][2] = -0.5;
+       cubeleft[1].u[1] = uv_ratio;
+       cubeleft[1].v[1] = 0.0;
+
+       cubeleft[1].verts[2][0] = 0.0;
+       cubeleft[1].verts[2][1] = sqrt_2 / 2.0;
+       cubeleft[1].verts[2][2] = 0.5;
+       cubeleft[1].u[2] = uv_ratio;
+       cubeleft[1].v[2] = uv_ratio;
+
+       nfacesleft = 2;
+       
+       /* Right face - two triangles */
+       cuberight[0].verts[0][0] = 0.0;
+       cuberight[0].verts[0][1] = sqrt_2 / 2.0;
+       cuberight[0].verts[0][2] = -0.5;
+       cuberight[0].u[0] = 0.0;
+       cuberight[0].v[0] = 0.0;
+
+       cuberight[0].verts[1][0] = sqrt_2 / 2.0;
+       cuberight[0].verts[1][1] = 0.0;
+       cuberight[0].verts[1][2] = -0.5;
+       cuberight[0].u[1] = uv_ratio;
+       cuberight[0].v[1] = 0.0;
+
+       cuberight[0].verts[2][0] = sqrt_2 / 2.0;
+       cuberight[0].verts[2][1] = 0.0;
+       cuberight[0].verts[2][2] = 0.5;
+       cuberight[0].u[2] = uv_ratio;
+       cuberight[0].v[2] = uv_ratio;
+
+       //second triangle
+       cuberight[1].verts[0][0] = 0.0;
+       cuberight[1].verts[0][1] = sqrt_2 / 2.0;
+       cuberight[1].verts[0][2] = -0.5;
+       cuberight[1].u[0] = 0.0;
+       cuberight[1].v[0] = 0.0;
+
+       cuberight[1].verts[1][0] = sqrt_2 / 2.0;
+       cuberight[1].verts[1][1] = 0.0;
+       cuberight[1].verts[1][2] = 0.5;
+       cuberight[1].u[1] = uv_ratio;
+       cuberight[1].v[1] = uv_ratio;
+
+       cuberight[1].verts[2][0] = 0.0;
+       cuberight[1].verts[2][1] = sqrt_2 / 2.0;
+       cuberight[1].verts[2][2] = 0.5;
+       cuberight[1].u[2] = 0.0;
+       cuberight[1].v[2] = uv_ratio;
+
+       nfacesright = 2;
+       
+       //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration
+       //Could be made more efficient for drawing if the triangles were ordered in a fan. Not that important since we are using DisplayLists
+
+       for(i=0;i<m_resolution;i++){
+               cubetop.resize(4*nfacestop);
+               SplitFace(cubetop,&nfacestop);
+               cubebottom.resize(4*nfacesbottom);
+               SplitFace(cubebottom,&nfacesbottom);    
+               cubeleft.resize(4*nfacesleft);
+               SplitFace(cubeleft,&nfacesleft);
+               cuberight.resize(4*nfacesright);
+               SplitFace(cuberight,&nfacesright);
+       }               
+
+       // Turn into a hemisphere
+       for(j=0;j<3;j++){
+               for(i=0;i<nfacestop;i++)
+                       cubetop[i].verts[j].normalize();
+               for(i=0;i<nfacesbottom;i++)
+                       cubebottom[i].verts[j].normalize();
+               for(i=0;i<nfacesleft;i++)
+                       cubeleft[i].verts[j].normalize();
+               for(i=0;i<nfacesright;i++)
+                       cuberight[i].verts[j].normalize();
+       }
+
+       //flatten onto xz plane
+       for(i=0;i<nfacestop;i++)
+               FlattenDome(cubetop[i].verts);
+       for(i=0;i<nfacesbottom;i++)
+               FlattenDome(cubebottom[i].verts);
+       for(i=0;i<nfacesleft;i++)
+               FlattenDome(cubeleft[i].verts);
+       for(i=0;i<nfacesright;i++)
+               FlattenDome(cuberight[i].verts);
+
+}
+
+void KX_Dome::CreateMeshDome250(void)
+{
+/*
+1)-  Define the faces of a cube without the back face
+ - each face is made out of 2 triangles
+2) Subdivide the faces
+ - more resolution == more curved lines
+3) Spherize the cube
+ - normalize the verts
+4) Flatten onto xz plane
+ - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image
+*/
+
+       int i,j;
+       float uv_height, uv_base;
+       float verts_height;
+
+       float rad_ang = m_angle * MT_PI / 180.0;
+       float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
+
+       m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening
+/*
+verts_height is the exactly needed height of the cube faces (not always 1.0).
+When we want some horizontal information (e.g. for horizontal 220º domes) we don't need to create and tesselate the whole cube.
+Therefore the lateral cube faces could be small, and the tesselate mesh would be completely used.
+(if we always worked with verts_height = 1.0, we would be discarding a lot of the calculated and tesselated geometry).
+
+So I came out with this formula:
+verts_height = tan((rad_ang/2) - (MT_PI/2))*sqrt(2.0);
+
+Here we take half the sphere(rad_ang/2) and subtract a quarter of it (MT_PI/2)
+Therefore we have the lenght in radians of the dome/sphere over the horizon.
+Once we take the tangent of that angle, you have the verts coordinate corresponding to the verts on the side faces.
+Then we need to multiply it by sqrt(2.0) to get the coordinate of the verts on the diagonal of the original cube.
+*/
+       verts_height = tan((rad_ang/2) - (MT_PI/2))*sqrt(2.0);
+
+       uv_height = uv_ratio * ((verts_height/2) + 0.5);
+       uv_base = uv_ratio * (1.0 - ((verts_height/2) + 0.5));
+       
+       //creating faces for the env mapcube 180º Dome
+       // Front Face - 2 triangles
+       cubefront[0].verts[0][0] =-1.0;
+       cubefront[0].verts[0][1] = 1.0;
+       cubefront[0].verts[0][2] =-1.0;
+       cubefront[0].u[0] = 0.0;
+       cubefront[0].v[0] = 0.0;
+
+       cubefront[0].verts[1][0] = 1.0;
+       cubefront[0].verts[1][1] = 1.0;
+       cubefront[0].verts[1][2] = 1.0; 
+       cubefront[0].u[1] = uv_ratio;
+       cubefront[0].v[1] = uv_ratio;
+
+       cubefront[0].verts[2][0] =-1.0;
+       cubefront[0].verts[2][1] = 1.0;
+       cubefront[0].verts[2][2] = 1.0; 
+       cubefront[0].u[2] = 0.0;
+       cubefront[0].v[2] = uv_ratio;
+
+       //second triangle
+       cubefront[1].verts[0][0] = 1.0;
+       cubefront[1].verts[0][1] = 1.0;
+       cubefront[1].verts[0][2] = 1.0;
+       cubefront[1].u[0] = uv_ratio;
+       cubefront[1].v[0] = uv_ratio;
+
+       cubefront[1].verts[1][0] =-1.0;
+       cubefront[1].verts[1][1] = 1.0;
+       cubefront[1].verts[1][2] =-1.0; 
+       cubefront[1].u[1] = 0.0;
+       cubefront[1].v[1] = 0.0;
+
+       cubefront[1].verts[2][0] = 1.0;
+       cubefront[1].verts[2][1] = 1.0;
+       cubefront[1].verts[2][2] =-1.0; 
+       cubefront[1].u[2] = uv_ratio;
+       cubefront[1].v[2] = 0.0;
+
+       nfacesfront = 2;
+
+       // Left Face - 2 triangles
+       cubeleft[0].verts[0][0] =-1.0;
+       cubeleft[0].verts[0][1] = 1.0;
+       cubeleft[0].verts[0][2] =-1.0;
+       cubeleft[0].u[0] = uv_ratio;
+       cubeleft[0].v[0] = 0.0;
+
+       cubeleft[0].verts[1][0] =-1.0;
+       cubeleft[0].verts[1][1] =-verts_height;
+       cubeleft[0].verts[1][2] = 1.0;  
+       cubeleft[0].u[1] = uv_base;
+       cubeleft[0].v[1] = uv_ratio;
+
+       cubeleft[0].verts[2][0] =-1.0;
+       cubeleft[0].verts[2][1] =-verts_height;
+       cubeleft[0].verts[2][2] =-1.0;  
+       cubeleft[0].u[2] = uv_base;
+       cubeleft[0].v[2] = 0.0;
+
+       //second triangle
+       cubeleft[1].verts[0][0] =-1.0;
+       cubeleft[1].verts[0][1] =-verts_height;
+       cubeleft[1].verts[0][2] = 1.0;
+       cubeleft[1].u[0] = uv_base;
+       cubeleft[1].v[0] = uv_ratio;
+
+       cubeleft[1].verts[1][0] =-1.0;
+       cubeleft[1].verts[1][1] = 1.0;
+       cubeleft[1].verts[1][2] =-1.0;  
+       cubeleft[1].u[1] = uv_ratio;
+       cubeleft[1].v[1] = 0.0;
+
+       cubeleft[1].verts[2][0] =-1.0;
+       cubeleft[1].verts[2][1] = 1.0;
+       cubeleft[1].verts[2][2] = 1.0;  
+       cubeleft[1].u[2] = uv_ratio;
+       cubeleft[1].v[2] = uv_ratio;
+
+       nfacesleft = 2;
+
+       // right Face - 2 triangles
+       cuberight[0].verts[0][0] = 1.0;
+       cuberight[0].verts[0][1] = 1.0;
+       cuberight[0].verts[0][2] = 1.0;
+       cuberight[0].u[0] = 0.0;
+       cuberight[0].v[0] = uv_ratio;
+
+       cuberight[0].verts[1][0] = 1.0;
+       cuberight[0].verts[1][1] =-verts_height;
+       cuberight[0].verts[1][2] =-1.0; 
+       cuberight[0].u[1] = uv_height;
+       cuberight[0].v[1] = 0.0;
+
+       cuberight[0].verts[2][0] = 1.0;
+       cuberight[0].verts[2][1] =-verts_height;
+       cuberight[0].verts[2][2] = 1.0; 
+       cuberight[0].u[2] = uv_height;
+       cuberight[0].v[2] = uv_ratio;
+
+       //second triangle
+       cuberight[1].verts[0][0] = 1.0;
+       cuberight[1].verts[0][1] =-verts_height;
+       cuberight[1].verts[0][2] =-1.0;
+       cuberight[1].u[0] = uv_height;
+       cuberight[1].v[0] = 0.0;
+
+       cuberight[1].verts[1][0] = 1.0;
+       cuberight[1].verts[1][1] = 1.0;
+       cuberight[1].verts[1][2] = 1.0; 
+       cuberight[1].u[1] = 0.0;
+       cuberight[1].v[1] = uv_ratio;
+
+       cuberight[1].verts[2][0] = 1.0;
+       cuberight[1].verts[2][1] = 1.0;
+       cuberight[1].verts[2][2] =-1.0; 
+       cuberight[1].u[2] = 0.0;
+       cuberight[1].v[2] = 0.0;
+
+       nfacesright = 2;
+
+       // top Face - 2 triangles
+       cubetop[0].verts[0][0] =-1.0;
+       cubetop[0].verts[0][1] = 1.0;
+       cubetop[0].verts[0][2] = 1.0;
+       cubetop[0].u[0] = 0.0;
+       cubetop[0].v[0] = 0.0;
+
+       cubetop[0].verts[1][0] = 1.0;
+       cubetop[0].verts[1][1] =-verts_height;
+       cubetop[0].verts[1][2] = 1.0;   
+       cubetop[0].u[1] = uv_ratio;
+       cubetop[0].v[1] = uv_height;
+
+       cubetop[0].verts[2][0] =-1.0;
+       cubetop[0].verts[2][1] =-verts_height;
+       cubetop[0].verts[2][2] = 1.0;   
+       cubetop[0].u[2] = 0.0;
+       cubetop[0].v[2] = uv_height;
+
+       //second triangle
+       cubetop[1].verts[0][0] = 1.0;
+       cubetop[1].verts[0][1] =-verts_height;
+       cubetop[1].verts[0][2] = 1.0;
+       cubetop[1].u[0] = uv_ratio;
+       cubetop[1].v[0] = uv_height;
+
+       cubetop[1].verts[1][0] =-1.0;
+       cubetop[1].verts[1][1] = 1.0;
+       cubetop[1].verts[1][2] = 1.0;   
+       cubetop[1].u[1] = 0.0;
+       cubetop[1].v[1] = 0.0;
+
+       cubetop[1].verts[2][0] = 1.0;
+       cubetop[1].verts[2][1] = 1.0;
+       cubetop[1].verts[2][2] = 1.0;   
+       cubetop[1].u[2] = uv_ratio;
+       cubetop[1].v[2] = 0.0;
+
+       nfacestop = 2;
+
+       // bottom Face - 2 triangles
+       cubebottom[0].verts[0][0] =-1.0;
+       cubebottom[0].verts[0][1] =-verts_height;
+       cubebottom[0].verts[0][2] =-1.0;
+       cubebottom[0].u[0] = 0.0;
+       cubebottom[0].v[0] = uv_base;
+
+       cubebottom[0].verts[1][0] = 1.0;
+       cubebottom[0].verts[1][1] = 1.0;
+       cubebottom[0].verts[1][2] =-1.0;        
+       cubebottom[0].u[1] = uv_ratio;
+       cubebottom[0].v[1] = uv_ratio;
+
+       cubebottom[0].verts[2][0] =-1.0;
+       cubebottom[0].verts[2][1] = 1.0;
+       cubebottom[0].verts[2][2] =-1.0;        
+       cubebottom[0].u[2] = 0.0;
+       cubebottom[0].v[2] = uv_ratio;
+
+       //second triangle
+       cubebottom[1].verts[0][0] = 1.0;
+       cubebottom[1].verts[0][1] = 1.0;
+       cubebottom[1].verts[0][2] =-1.0;
+       cubebottom[1].u[0] = uv_ratio;
+       cubebottom[1].v[0] = uv_ratio;
+
+       cubebottom[1].verts[1][0] =-1.0;
+       cubebottom[1].verts[1][1] =-verts_height;
+       cubebottom[1].verts[1][2] =-1.0;        
+       cubebottom[1].u[1] = 0.0;
+       cubebottom[1].v[1] = uv_base;
+
+       cubebottom[1].verts[2][0] = 1.0;
+       cubebottom[1].verts[2][1] =-verts_height;
+       cubebottom[1].verts[2][2] =-1.0;        
+       cubebottom[1].u[2] = uv_ratio;
+       cubebottom[1].v[2] = uv_base;
+
+       nfacesbottom = 2;
+
+       //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration
+       //It could be made more efficient for drawing if the triangles were ordered in a strip!
+
+       for(i=0;i<m_resolution;i++){
+               cubefront.resize(4*nfacesfront);
+               SplitFace(cubefront,&nfacesfront);
+               cubetop.resize(4*nfacestop);
+               SplitFace(cubetop,&nfacestop);
+               cubebottom.resize(4*nfacesbottom);
+               SplitFace(cubebottom,&nfacesbottom);    
+               cubeleft.resize(4*nfacesleft);
+               SplitFace(cubeleft,&nfacesleft);
+               cuberight.resize(4*nfacesright);
+               SplitFace(cuberight,&nfacesright);
+       }
+
+       // Turn into a hemisphere/sphere
+       for(j=0;j<3;j++){
+               for(i=0;i<nfacesfront;i++)
+                       cubefront[i].verts[j].normalize();
+               for(i=0;i<nfacestop;i++)
+                       cubetop[i].verts[j].normalize();
+               for(i=0;i<nfacesbottom;i++)
+                       cubebottom[i].verts[j].normalize();
+               for(i=0;i<nfacesleft;i++)
+                       cubeleft[i].verts[j].normalize();
+               for(i=0;i<nfacesright;i++)
+                       cuberight[i].verts[j].normalize();
+       }
+
+       //flatten onto xz plane
+       for(i=0;i<nfacesfront;i++)
+               FlattenDome(cubefront[i].verts);        
+       for(i=0;i<nfacestop;i++)
+               FlattenDome(cubetop[i].verts);
+       for(i=0;i<nfacesbottom;i++)
+               FlattenDome(cubebottom[i].verts);
+       for(i=0;i<nfacesleft;i++)
+               FlattenDome(cubeleft[i].verts);         
+       for(i=0;i<nfacesright;i++)
+               FlattenDome(cuberight[i].verts);
+}
+
+void KX_Dome::CreateMeshPanorama(void)
+{
+/*
+1)-  Define the faces of a cube without the top and bottom faces
+ - each face is made out of 2 triangles
+2) Subdivide the faces
+ - more resolution == more curved lines
+3) Spherize the cube
+ - normalize the verts t
+4) Flatten onto xz plane
+ - use spherical projection techniques to transform the sphere onto a flat panorama
+*/
+       int i,j;
+
+       float sqrt_2 = sqrt(2.0);
+       float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
+
+       /* Top face - two triangles */
+       cubetop[0].verts[0][0] = -sqrt_2;
+       cubetop[0].verts[0][1] = 0.0;
+       cubetop[0].verts[0][2] = 1.0;
+       cubetop[0].u[0] = 0.0;
+       cubetop[0].v[0] = uv_ratio;
+
+       cubetop[0].verts[1][0] = 0.0;
+       cubetop[0].verts[1][1] = sqrt_2;
+       cubetop[0].verts[1][2] = 1.0;
+       cubetop[0].u[1] = 0.0;
+       cubetop[0].v[1] = 0.0;
+
+       //second triangle
+       cubetop[0].verts[2][0] = sqrt_2;
+       cubetop[0].verts[2][1] = 0.0;
+       cubetop[0].verts[2][2] = 1.0;
+       cubetop[0].u[2] = uv_ratio;
+       cubetop[0].v[2] = 0.0;
+
+       cubetop[1].verts[0][0] = sqrt_2;
+       cubetop[1].verts[0][1] = 0.0;
+       cubetop[1].verts[0][2] = 1.0;
+       cubetop[1].u[0] = uv_ratio;
+       cubetop[1].v[0] = 0.0;
+
+       cubetop[1].verts[1][0] = 0.0;
+       cubetop[1].verts[1][1] = -sqrt_2;
+       cubetop[1].verts[1][2] = 1.0;
+       cubetop[1].u[1] = uv_ratio;
+       cubetop[1].v[1] = uv_ratio;
+
+       cubetop[1].verts[2][0] = -sqrt_2;
+       cubetop[1].verts[2][1] = 0.0;
+       cubetop[1].verts[2][2] = 1.0;
+       cubetop[1].u[2] = 0.0;
+       cubetop[1].v[2] = uv_ratio;
+
+       nfacestop = 2;
+
+       /* Bottom face - two triangles */
+       cubebottom[0].verts[0][0] = -sqrt_2;
+       cubebottom[0].verts[0][1] = 0.0;
+       cubebottom[0].verts[0][2] = -1.0;
+       cubebottom[0].u[0] = uv_ratio;
+       cubebottom[0].v[0] = 0.0;
+
+       cubebottom[0].verts[1][0] = sqrt_2;
+       cubebottom[0].verts[1][1] = 0.0;
+       cubebottom[0].verts[1][2] = -1.0;
+       cubebottom[0].u[1] = 0.0;
+       cubebottom[0].v[1] = uv_ratio;
+
+       cubebottom[0].verts[2][0] = 0.0;
+       cubebottom[0].verts[2][1] = sqrt_2;
+       cubebottom[0].verts[2][2] = -1.0;
+       cubebottom[0].u[2] = 0.0;
+       cubebottom[0].v[2] = 0.0;
+
+       //second triangle
+       cubebottom[1].verts[0][0] = sqrt_2;
+       cubebottom[1].verts[0][1] = 0.0;
+       cubebottom[1].verts[0][2] = -1.0;
+       cubebottom[1].u[0] = 0.0;
+       cubebottom[1].v[0] = uv_ratio;
+
+       cubebottom[1].verts[1][0] = -sqrt_2;
+       cubebottom[1].verts[1][1] = 0.0;
+       cubebottom[1].verts[1][2] = -1.0;
+       cubebottom[1].u[1] = uv_ratio;
+       cubebottom[1].v[1] = 0.0;
+
+       cubebottom[1].verts[2][0] = 0.0;
+       cubebottom[1].verts[2][1] = -sqrt_2;
+       cubebottom[1].verts[2][2] = -1.0;
+       cubebottom[1].u[2] = uv_ratio;
+       cubebottom[1].v[2] = uv_ratio;
+
+       nfacesbottom = 2;
+
+       /* Left Back (135º) face - two triangles */
+
+       cubeleftback[0].verts[0][0] = 0;
+       cubeleftback[0].verts[0][1] = -sqrt_2;
+       cubeleftback[0].verts[0][2] = -1.0;
+       cubeleftback[0].u[0] = 0;
+       cubeleftback[0].v[0] = 0;
+
+       cubeleftback[0].verts[1][0] = -sqrt_2;
+       cubeleftback[0].verts[1][1] = 0;
+       cubeleftback[0].verts[1][2] = -1.0;
+       cubeleftback[0].u[1] = uv_ratio;
+       cubeleftback[0].v[1] = 0;
+
+       cubeleftback[0].verts[2][0] = 0;
+       cubeleftback[0].verts[2][1] = -sqrt_2;
+       cubeleftback[0].verts[2][2] = 1.0;
+       cubeleftback[0].u[2] = 0;
+       cubeleftback[0].v[2] = uv_ratio;
+
+       //second triangle
+       cubeleftback[1].verts[0][0] = 0;
+       cubeleftback[1].verts[0][1] = -sqrt_2;
+       cubeleftback[1].verts[0][2] = 1.0;
+       cubeleftback[1].u[0] = 0;
+       cubeleftback[1].v[0] = uv_ratio;
+
+       cubeleftback[1].verts[1][0] = -sqrt_2;
+       cubeleftback[1].verts[1][1] = 0;
+       cubeleftback[1].verts[1][2] = -1.0;
+       cubeleftback[1].u[1] = uv_ratio;
+       cubeleftback[1].v[1] = 0;
+
+       cubeleftback[1].verts[2][0] = -sqrt_2;
+       cubeleftback[1].verts[2][1] = 0;
+       cubeleftback[1].verts[2][2] = 1.0;
+       cubeleftback[1].u[2] = uv_ratio;
+       cubeleftback[1].v[2] = uv_ratio;
+
+       nfacesleftback = 2;
+
+       /* Left face - two triangles */
+       
+       cubeleft[0].verts[0][0] = -sqrt_2;
+       cubeleft[0].verts[0][1] = 0;
+       cubeleft[0].verts[0][2] = -1.0;
+       cubeleft[0].u[0] = 0;
+       cubeleft[0].v[0] = 0;
+
+       cubeleft[0].verts[1][0] = 0;
+       cubeleft[0].verts[1][1] = sqrt_2;
+       cubeleft[0].verts[1][2] = -1.0;
+       cubeleft[0].u[1] = uv_ratio;
+       cubeleft[0].v[1] = 0;
+
+       cubeleft[0].verts[2][0] = -sqrt_2;
+       cubeleft[0].verts[2][1] = 0;
+       cubeleft[0].verts[2][2] = 1.0;
+       cubeleft[0].u[2] = 0;
+       cubeleft[0].v[2] = uv_ratio;
+
+       //second triangle
+       cubeleft[1].verts[0][0] = -sqrt_2;
+       cubeleft[1].verts[0][1] = 0;
+       cubeleft[1].verts[0][2] = 1.0;
+       cubeleft[1].u[0] = 0;
+       cubeleft[1].v[0] = uv_ratio;
+
+       cubeleft[1].verts[1][0] = 0;
+       cubeleft[1].verts[1][1] = sqrt_2;
+       cubeleft[1].verts[1][2] = -1.0;
+       cubeleft[1].u[1] = uv_ratio;
+       cubeleft[1].v[1] = 0;
+
+       cubeleft[1].verts[2][0] = 0;
+       cubeleft[1].verts[2][1] = sqrt_2;
+       cubeleft[1].verts[2][2] = 1.0;
+       cubeleft[1].u[2] = uv_ratio;
+       cubeleft[1].v[2] = uv_ratio;
+
+       nfacesleft = 2;
+       
+       /* Right face - two triangles */
+       cuberight[0].verts[0][0] = 0;
+       cuberight[0].verts[0][1] = sqrt_2;
+       cuberight[0].verts[0][2] = -1.0;
+       cuberight[0].u[0] = 0;
+       cuberight[0].v[0] = 0;
+
+       cuberight[0].verts[1][0] = sqrt_2;
+       cuberight[0].verts[1][1] = 0;
+       cuberight[0].verts[1][2] = -1.0;
+       cuberight[0].u[1] = uv_ratio;
+       cuberight[0].v[1] = 0;
+
+       cuberight[0].verts[2][0] = sqrt_2;
+       cuberight[0].verts[2][1] = 0;
+       cuberight[0].verts[2][2] = 1.0;
+       cuberight[0].u[2] = uv_ratio;
+       cuberight[0].v[2] = uv_ratio;
+
+       //second triangle
+       cuberight[1].verts[0][0] = 0;
+       cuberight[1].verts[0][1] = sqrt_2;
+       cuberight[1].verts[0][2] = -1.0;
+       cuberight[1].u[0] = 0;
+       cuberight[1].v[0] = 0;
+
+       cuberight[1].verts[1][0] = sqrt_2;
+       cuberight[1].verts[1][1] = 0;
+       cuberight[1].verts[1][2] = 1.0;
+       cuberight[1].u[1] = uv_ratio;
+       cuberight[1].v[1] = uv_ratio;
+
+       cuberight[1].verts[2][0] = 0;
+       cuberight[1].verts[2][1] = sqrt_2;
+       cuberight[1].verts[2][2] = 1.0;
+       cuberight[1].u[2] = 0;
+       cuberight[1].v[2] = uv_ratio;
+
+       nfacesright = 2;
+       
+       /* Right Back  (-135º) face - two triangles */
+       cuberightback[0].verts[0][0] = sqrt_2;
+       cuberightback[0].verts[0][1] = 0;
+       cuberightback[0].verts[0][2] = -1.0;
+       cuberightback[0].u[0] = 0;
+       cuberightback[0].v[0] = 0;
+
+       cuberightback[0].verts[1][0] = 0;
+       cuberightback[0].verts[1][1] = -sqrt_2;
+       cuberightback[0].verts[1][2] = -1.0;
+       cuberightback[0].u[1] = uv_ratio;
+       cuberightback[0].v[1] = 0;
+
+       cuberightback[0].verts[2][0] = 0;
+       cuberightback[0].verts[2][1] = -sqrt_2;
+       cuberightback[0].verts[2][2] = 1.0;
+       cuberightback[0].u[2] = uv_ratio;
+       cuberightback[0].v[2] = uv_ratio;
+
+       //second triangle
+       cuberightback[1].verts[0][0] = sqrt_2;
+       cuberightback[1].verts[0][1] = 0;
+       cuberightback[1].verts[0][2] = -1.0;
+       cuberightback[1].u[0] = 0;
+       cuberightback[1].v[0] = 0;
+
+       cuberightback[1].verts[1][0] = 0;
+       cuberightback[1].verts[1][1] = -sqrt_2;
+       cuberightback[1].verts[1][2] = 1.0;
+       cuberightback[1].u[1] = uv_ratio;
+       cuberightback[1].v[1] = uv_ratio;
+
+       cuberightback[1].verts[2][0] = sqrt_2;
+       cuberightback[1].verts[2][1] = 0;
+       cuberightback[1].verts[2][2] = 1.0;
+       cuberightback[1].u[2] = 0;
+       cuberightback[1].v[2] = uv_ratio;
+
+       nfacesrightback = 2;
+
+       // Subdivide the faces
+       for(i=0;i<m_resolution;i++)
+       {
+               cubetop.resize(4*nfacestop);
+               SplitFace(cubetop,&nfacestop);
+
+               cubebottom.resize(4*nfacesbottom);
+               SplitFace(cubebottom,&nfacesbottom);
+
+               cubeleft.resize(4*nfacesleft);
+               SplitFace(cubeleft,&nfacesleft);
+
+               cuberight.resize(4*nfacesright);
+               SplitFace(cuberight,&nfacesright);
+
+               cubeleftback.resize(4*nfacesleftback);
+               SplitFace(cubeleftback,&nfacesleftback);
+
+               cuberightback.resize(4*nfacesrightback);
+               SplitFace(cuberightback,&nfacesrightback);
+       }
+
+       // Spherize the cube
+       for(j=0;j<3;j++)
+       {
+               for(i=0;i<nfacestop;i++)
+                       cubetop[i].verts[j].normalize();
+
+               for(i=0;i<nfacesbottom;i++)
+                       cubebottom[i].verts[j].normalize();
+
+               for(i=0;i<nfacesleftback;i++)
+                       cubeleftback[i].verts[j].normalize();
+
+               for(i=0;i<nfacesleft;i++)
+                       cubeleft[i].verts[j].normalize();
+
+               for(i=0;i<nfacesright;i++)
+                       cuberight[i].verts[j].normalize();
+
+               for(i=0;i<nfacesrightback;i++)
+                       cuberightback[i].verts[j].normalize();
+       }
+
+       //Flatten onto xz plane
+       for(i=0;i<nfacesleftback;i++)
+               FlattenPanorama(cubeleftback[i].verts);
+
+       for(i=0;i<nfacesleft;i++)
+               FlattenPanorama(cubeleft[i].verts);
+
+       for(i=0;i<nfacesright;i++)
+               FlattenPanorama(cuberight[i].verts);
+
+       for(i=0;i<nfacesrightback;i++)
+               FlattenPanorama(cuberightback[i].verts);
+
+       for(i=0;i<nfacestop;i++)
+               FlattenPanorama(cubetop[i].verts);
+
+       for(i=0;i<nfacesbottom;i++)
+               FlattenPanorama(cubebottom[i].verts);
+}
+
+void KX_Dome::FlattenDome(MT_Vector3 verts[3])
+{
+       double phi, r;
+
+       for (int i=0;i<3;i++){
+               r = atan2(sqrt(verts[i][0]*verts[i][0] + verts[i][2]*verts[i][2]), verts[i][1]);
+               r /= m_radangle/2;
+
+               phi = atan2(verts[i][2], verts[i][0]);
+
+               verts[i][0] = r * cos(phi);
+               verts[i][1] = 0;
+               verts[i][2] = r * sin(phi);
+
+               if (r > 1.0){
+               //round the border
+                       verts[i][0] = cos(phi);
+                       verts[i][1] = -3.0;
+                       verts[i][2] = sin(phi);
+               }
+       }
+}
+
+void KX_Dome::FlattenPanorama(MT_Vector3 verts[3])
+{
+// it creates a full spherical panoramic (360º)
+       int i;
+       double phi;
+       bool edge=false;
+
+       for (i=0;i<3;i++){
+               phi = atan2(verts[i][1], verts[i][0]);
+               phi *= -1.0; //flipping
+
+               if (phi == -MT_PI) //It's on the edge
+                       edge=true;
+
+               verts[i][0] = phi / MT_PI;
+               verts[i][1] = 0;
+
+               verts[i][2] = atan2(verts[i][2], 1.0);
+               verts[i][2] /= MT_PI / 2;
+       }
+       if(edge){
+               bool right=false;
+
+               for (i=0;i<3;i++){
+                       if(fmod(verts[i][0],1.0) > 0.0){
+                               right=true;
+                               break;
+                       }
+               }
+               if(right){
+                       for (i=0;i<3;i++){
+                               if(verts[i][0] < 0.0)
+                                       verts[i][0] *= -1.0;
+                       }
+               }
+       }
+}
+
+void KX_Dome::SplitFace(vector <DomeFace>& face, int *nfaces)
+{
+       int i;
+       int n1, n2;
+
+       n1 = n2 = *nfaces;
+
+       for(i=0;i<n1;i++){
+
+               face[n2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2;
+               face[n2].verts[1] =  face[i].verts[1];
+               face[n2].verts[2] = (face[i].verts[1] + face[i].verts[2]) /2;
+               face[n2].u[0]     = (face[i].u[0] + face[i].u[1]) /2;
+               face[n2].u[1]     =  face[i].u[1];
+               face[n2].u[2]     = (face[i].u[1] + face[i].u[2]) /2;
+               face[n2].v[0]     = (face[i].v[0] + face[i].v[1]) /2;
+               face[n2].v[1]     =  face[i].v[1];
+               face[n2].v[2]     = (face[i].v[1] + face[i].v[2]) /2;
+
+               face[n2+1].verts[0] = (face[i].verts[1] + face[i].verts[2]) /2;
+               face[n2+1].verts[1] =  face[i].verts[2];
+               face[n2+1].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2;
+               face[n2+1].u[0]         = (face[i].u[1] + face[i].u[2]) /2;
+               face[n2+1].u[1]         =  face[i].u[2];
+               face[n2+1].u[2]         = (face[i].u[2] + face[i].u[0]) /2;
+               face[n2+1].v[0]         = (face[i].v[1] + face[i].v[2]) /2;
+               face[n2+1].v[1]         =  face[i].v[2];
+               face[n2+1].v[2]         = (face[i].v[2] + face[i].v[0]) /2;
+
+               face[n2+2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2;
+               face[n2+2].verts[1] = (face[i].verts[1] + face[i].verts[2]) /2;
+               face[n2+2].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2;
+               face[n2+2].u[0]   = (face[i].u[0] + face[i].u[1]) /2;
+               face[n2+2].u[1]   = (face[i].u[1] + face[i].u[2]) /2;
+               face[n2+2].u[2]   = (face[i].u[2] + face[i].u[0]) /2;
+               face[n2+2].v[0]   = (face[i].v[0] + face[i].v[1]) /2;
+               face[n2+2].v[1]   = (face[i].v[1] + face[i].v[2]) /2;
+               face[n2+2].v[2]   = (face[i].v[2] + face[i].v[0]) /2;           
+
+               //face[i].verts[0] = face[i].verts[0] ;
+               face[i].verts[1] = (face[i].verts[0] + face[i].verts[1]) /2;
+               face[i].verts[2] = (face[i].verts[0] + face[i].verts[2]) /2;
+               //face[i].u[0]   =  face[i].u[0];
+               face[i].u[1]     = (face[i].u[0] + face[i].u[1]) /2;
+               face[i].u[2]     = (face[i].u[0] + face[i].u[2]) /2;
+               //face[i].v[0]   = face[i].v[0] ;
+               face[i].v[1]     = (face[i].v[0] + face[i].v[1]) /2;
+               face[i].v[2]     = (face[i].v[0] + face[i].v[2]) /2;            
+
+               n2 += 3; // number of faces
+       }
+       *nfaces = n2;
+}
+
+void KX_Dome::CalculateFrustum(KX_Camera * cam)
+{
+       /*
+       // manually creating a 90º Field of View Frustum 
+
+        the original formula:
+       top = tan(fov*3.14159/360.0) * near [for fov in degrees]
+       fov*0.5 = arctan ((top-bottom)*0.5 / near) [for fov in radians]
+       bottom = -top
+       left = aspect * bottom
+       right = aspect * top
+
+       // the equivalent GLU call is:
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       gluPerspective(90.0,1.0,cam->GetCameraNear(),cam->GetCameraFar());
+       */
+
+       RAS_FrameFrustum m_frustrum; //90 deg. Frustum
+
+       m_frustrum.camnear = cam->GetCameraNear();
+       m_frustrum.camfar = cam->GetCameraFar();
+
+//     float top = tan(90.0*MT_PI/360.0) * m_frustrum.camnear;
+       float top = m_frustrum.camnear; // for deg = 90º, tan = 1
+
+       m_frustrum.x1 = -top;
+       m_frustrum.x2 = top;
+       m_frustrum.y1 = -top;
+       m_frustrum.y2 = top;
+       
+       m_projmat = m_rasterizer->GetFrustumMatrix(
+       m_frustrum.x1, m_frustrum.x2, m_frustrum.y1, m_frustrum.y2, m_frustrum.camnear, m_frustrum.camfar);
+
+}
+
+void KX_Dome::CalculateCameraOrientation()
+{
+/*
+Uses 4 cameras for angles up to 180º
+Uses 5 cameras for angles up to 250º
+Uses 6 cameras for angles up to 360º
+*/
+       float deg45 = MT_PI / 4;
+       MT_Scalar c = cos(deg45);
+       MT_Scalar s = sin(deg45);
+
+       if ((m_mode == DOME_FISHEYE && m_angle <= 180)|| m_mode == DOME_TRUNCATED){
+
+               m_locRot[0] = MT_Matrix3x3( // 90º - Top
+                                               c, -s, 0.0,
+                                               0.0,0.0, -1.0,
+                                               s, c, 0.0);
+
+               m_locRot[1] = MT_Matrix3x3( // 90º - Bottom
+                                               -s, c, 0.0,
+                                               0.0,0.0, 1.0,
+                                               s, c, 0.0);
+
+               m_locRot[2] = MT_Matrix3x3( // 45º - Left
+                                               c, 0.0, s,
+                                               0, 1.0, 0.0,
+                                               -s, 0.0, c);
+
+               m_locRot[3] = MT_Matrix3x3( // 45º - Right
+                                               c, 0.0, -s,
+                                               0.0, 1.0, 0.0,
+                                               s, 0.0, c);
+
+       } else if ((m_mode == DOME_FISHEYE && m_angle > 180)){
+
+               m_locRot[0] = MT_Matrix3x3( // 90º - Top
+                                                1.0, 0.0, 0.0,
+                                                0.0, 0.0,-1.0,
+                                                0.0, 1.0, 0.0);
+
+               m_locRot[1] = MT_Matrix3x3( // 90º - Bottom
+                                                1.0, 0.0, 0.0,
+                                                0.0, 0.0, 1.0,
+                                                0.0,-1.0, 0.0);
+
+               m_locRot[2] = MT_Matrix3x3( // -90º - Left
+                                                0.0, 0.0, 1.0,
+                                                0.0, 1.0, 0.0,
+                                                -1.0, 0.0, 0.0);
+
+               m_locRot[3] = MT_Matrix3x3( // 90º - Right
+                                                0.0, 0.0,-1.0,
+                                                0.0, 1.0, 0.0,
+                                                1.0, 0.0, 0.0);
+                                               
+               m_locRot[4] = MT_Matrix3x3( // 0º - Front
+                                               1.0, 0.0, 0.0,
+                                               0.0, 1.0, 0.0,
+                                               0.0, 0.0, 1.0);
+
+               m_locRot[5] = MT_Matrix3x3( // 180º - Back - NOT USING
+                                               -1.0, 0.0, 0.0,
+                                                0.0, 1.0, 0.0,
+                                                0.0, 0.0,-1.0);
+
+       } else if (m_mode == DOME_PANORAM_SPH){
+
+               m_locRot[0] = MT_Matrix3x3( // Top 
+                                               c, s, 0.0,
+                                               0.0,0.0, -1.0,
+                                               -s, c, 0.0);
+
+               m_locRot[1] = MT_Matrix3x3( // Bottom
+                                               c, s, 0.0,
+                                               0.0 ,0.0, 1.0,
+                                               s, -c, 0.0);
+
+               m_locRot[2] = MT_Matrix3x3( // 45º - Left
+                                               -s, 0.0, c,
+                                               0, 1.0, 0.0,
+                                               -c, 0.0, -s);
+
+               m_locRot[3] = MT_Matrix3x3( // 45º - Right
+                                               c, 0.0, s,
+                                               0, 1.0, 0.0,
+                                               -s, 0.0, c);
+
+               m_locRot[4] = MT_Matrix3x3( // 135º - LeftBack
+                                               -s, 0.0, -c,
+                                               0.0, 1.0, 0.0,
+                                               c, 0.0, -s);
+
+               m_locRot[5] = MT_Matrix3x3( // 135º - RightBack
+                                               c, 0.0, -s,
+                                               0.0, 1.0, 0.0,
+                                               s, 0.0, c);
+       }
+}
+
+void KX_Dome::RotateCamera(KX_Camera* cam, int i)
+{
+// I'm not using it, I'm doing inline calls for these commands
+// but it's nice to have it here in case I need it
+
+       MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation();
+
+       cam->NodeSetLocalOrientation(camori*m_locRot[i]);
+       cam->NodeUpdateGS(0.f);
+
+       MT_Transform camtrans(cam->GetWorldToCamera());
+       MT_Matrix4x4 viewmat(camtrans);
+       m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
+               cam->GetCameraLocation(), cam->GetCameraOrientation());
+       cam->SetModelviewMatrix(viewmat);
+
+       // restore the original orientation
+       cam->NodeSetLocalOrientation(camori);
+       cam->NodeUpdateGS(0.f);
+}
+
+void KX_Dome::Draw(void)
+{
+
+       switch(m_mode){
+               case DOME_FISHEYE:
+                       DrawDomeFisheye();
+                       break;
+               case DOME_TRUNCATED:
+                       DrawDomeFisheye();
+                       break;
+               case DOME_PANORAM_SPH:
+                       DrawPanorama();
+                       break;
+       }
+
+       if(warp.usemesh)
+       {
+               glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
+               glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight);
+               DrawDomeWarped();
+       }
+}
+
+void KX_Dome::DrawDomeFisheye(void)
+{
+       int i,j;
+
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+
+       // Making the viewport always square 
+
+       int can_width = m_viewport.GetRight();
+       int can_height = m_viewport.GetTop();
+
+       float ortho_width, ortho_height;
+
+       if (warp.usemesh)
+               glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost
+
+       else if(m_mode == DOME_TRUNCATED){
+               ortho_width = 1.0;
+               ortho_height = 2 * ((float)can_height/can_width) - 1.0 ;
+               
+               ortho_width /= m_size;
+               ortho_height /= m_size;
+
+               glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0);
+       } else {
+               if (can_width < can_height){
+                       ortho_width = 1.0;
+                       ortho_height = (float)can_height/can_width;
+               }else{
+                       ortho_width = (float)can_width/can_height;
+                       ortho_height = 1.0;
+               }
+               
+               ortho_width /= m_size;
+               ortho_height /= m_size;
+               
+               glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
+       }
+
+       glMatrixMode(GL_TEXTURE);
+       glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0);
+
+       if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
+               glPolygonMode(GL_FRONT, GL_LINE);
+       else
+               glPolygonMode(GL_FRONT, GL_FILL);
+
+       glShadeModel(GL_SMOOTH);
+       glDisable(GL_LIGHTING);
+       glDisable(GL_DEPTH_TEST);
+
+       glEnable(GL_TEXTURE_2D);
+       glColor3f(1.0,1.0,1.0);
+
+       if (dlistSupported){
+               for(i=0;i<m_numfaces;i++){
+                       glBindTexture(GL_TEXTURE_2D, domefacesId[i]);
+                       glCallList(dlistId+i);
+               }
+       }
+       else { // DisplayLists not supported
+               // top triangle
+               glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
+               GLDrawTriangles(cubetop, nfacestop);
+
+               // bottom triangle      
+               glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
+               GLDrawTriangles(cubebottom, nfacesbottom);
+
+               // left triangle
+               glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
+               GLDrawTriangles(cubeleft, nfacesleft);
+
+               // right triangle
+               glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
+               GLDrawTriangles(cuberight, nfacesright);
+
+               if (m_angle > 180){
+                       // front triangle
+                       glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
+                       GLDrawTriangles(cubefront, nfacesfront);
+               }
+       }
+       glDisable(GL_TEXTURE_2D);
+       glEnable(GL_DEPTH_TEST);
+}
+
+void KX_Dome::DrawPanorama(void)
+{
+       int i,j;
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+
+       // Making the viewport always square 
+
+       int can_width = m_viewport.GetRight();
+       int can_height = m_viewport.GetTop();
+
+       float ortho_height = 1.0;
+       float ortho_width = 1.0;
+
+       if (warp.usemesh)
+               glOrtho((-1.0), 1.0, (-0.5), 0.5, -20.0, 10.0); //stretch the image to reduce resolution lost
+
+       else {
+               //using all the screen
+               if ((can_width / 2) <= (can_height)){
+                       ortho_width = 1.0;
+                       ortho_height = (float)can_height/can_width;
+               }else{
+                       ortho_width = (float)can_width/can_height * 0.5;
+                       ortho_height = 0.5;
+               }
+
+               ortho_width /= m_size;
+               ortho_height /= m_size;
+               
+               glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
+       }
+
+       glMatrixMode(GL_TEXTURE);
+       glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0);
+
+       if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
+               glPolygonMode(GL_FRONT, GL_LINE);
+       else
+               glPolygonMode(GL_FRONT, GL_FILL);
+
+       glShadeModel(GL_SMOOTH);
+       glDisable(GL_LIGHTING);
+       glDisable(GL_DEPTH_TEST);
+
+       glEnable(GL_TEXTURE_2D);
+       glColor3f(1.0,1.0,1.0);
+
+       if (dlistSupported){
+               for(i=0;i<m_numfaces;i++){
+                       glBindTexture(GL_TEXTURE_2D, domefacesId[i]);
+                       glCallList(dlistId+i);
+               }
+       }
+       else {
+               // domefacesId[4] =>  (top)
+               glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
+                       GLDrawTriangles(cubetop, nfacestop);
+
+               // domefacesId[5] =>  (bottom)
+               glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
+                       GLDrawTriangles(cubebottom, nfacesbottom);
+
+               // domefacesId[1] => -45º (left)
+               glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
+                       GLDrawTriangles(cubeleft, nfacesleft);
+
+               // domefacesId[2] => 45º (right)
+               glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
+                       GLDrawTriangles(cuberight, nfacesright);
+
+               // domefacesId[0] => -135º (leftback)
+               glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
+                       GLDrawTriangles(cubeleftback, nfacesleftback);
+
+               // domefacesId[3] => 135º (rightback)
+               glBindTexture(GL_TEXTURE_2D, domefacesId[5]);
+                       GLDrawTriangles(cuberightback, nfacesrightback);
+       }
+       glDisable(GL_TEXTURE_2D);
+       glEnable(GL_DEPTH_TEST);
+}
+
+void KX_Dome::DrawDomeWarped(void)
+{
+       int i,j;
+
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+
+       // Making the viewport always square 
+       int can_width = m_viewport.GetRight();
+       int can_height = m_viewport.GetTop();
+
+       double screen_ratio = can_width/ (double) can_height;   
+       screen_ratio /= m_size;
+
+    glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0);
+
+
+       glMatrixMode(GL_TEXTURE);
+       glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       gluLookAt(0.0, 0.0, 1.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
+
+       if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
+               glPolygonMode(GL_FRONT, GL_LINE);
+       else
+               glPolygonMode(GL_FRONT, GL_FILL);
+
+       glShadeModel(GL_SMOOTH);
+       glDisable(GL_LIGHTING);
+       glDisable(GL_DEPTH_TEST);
+
+       glEnable(GL_TEXTURE_2D);
+       glColor3f(1.0,1.0,1.0);
+
+
+       float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth;
+       float uv_height = (float)(warp.bufferheight-1) / warp.imageheight;
+
+       if (dlistSupported){
+               glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
+               glCallList(dlistId + m_numfaces);
+       }
+       else{
+               glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
+               GLDrawWarpQuads();
+       }
+       glDisable(GL_TEXTURE_2D);
+       glEnable(GL_DEPTH_TEST);
+}
+
+void KX_Dome::BindImages(int i)
+{
+       glBindTexture(GL_TEXTURE_2D, domefacesId[i]);
+       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), m_buffersize, m_buffersize);
+}
+
+void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
+{
+       if (!cam)
+               return;
+
+       m_canvas->SetViewPort(0,0,m_buffersize-1,m_buffersize-1);
+
+//     m_rasterizer->SetAmbient();
+       m_rasterizer->DisplayFog();
+
+       CalculateFrustum(cam); //calculates m_projmat
+       cam->SetProjectionMatrix(m_projmat);
+       m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
+//     Dome_RotateCamera(cam,i);
+
+       MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation();
+
+       cam->NodeSetLocalOrientation(camori*m_locRot[i]);
+       cam->NodeUpdateGS(0.f);
+
+       MT_Transform camtrans(cam->GetWorldToCamera());
+       MT_Matrix4x4 viewmat(camtrans);
+       m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
+               cam->GetCameraLocation(), cam->GetCameraOrientation());
+       cam->SetModelviewMatrix(viewmat);
+
+       scene->CalculateVisibleMeshes(m_rasterizer,cam);
+       scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
+       
+       // restore the original orientation
+       cam->NodeSetLocalOrientation(camori);
+       cam->NodeUpdateGS(0.f);
+}
\ No newline at end of file
diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h
new file mode 100644 (file)
index 0000000..de3360c
--- /dev/null
@@ -0,0 +1,183 @@
+/* $Id$
+-----------------------------------------------------------------------------
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+
+Contributor(s): Dalai Felinto
+
+This source uses some of the ideas and code from Paul Bourke.
+Developed as part of a Research and Development project for SAT - La Société des arts technologiques.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined KX_DOME_H
+#define KX_DOME_H
+
+#include "KX_Scene.h"
+#include "KX_Camera.h"
+#include "DNA_screen_types.h"
+#include "RAS_ICanvas.h"
+#include "RAS_IRasterizer.h"
+#include "RAS_IRenderTools.h"
+#include "KX_KetsjiEngine.h"
+
+#include <BIF_gl.h>
+#include <vector>
+
+#include "MEM_guardedalloc.h"
+#include "BKE_text.h"
+//#include "BLI_blenlib.h"
+
+//Dome modes: limit hardcoded in buttons_scene.c
+#define DOME_FISHEYE           1
+#define DOME_TRUNCATED         2
+#define DOME_PANORAM_SPH       3
+#define DOME_NUM_MODES         4
+
+
+/// class for render 3d scene
+class KX_Dome
+{
+public:
+       /// constructor
+       KX_Dome (
+       RAS_ICanvas* m_canvas,
+    /// rasterizer
+    RAS_IRasterizer* m_rasterizer,
+    /// render tools
+    RAS_IRenderTools* m_rendertools,
+    /// engine
+    KX_KetsjiEngine* m_engine,
+       
+       float size,
+       short res,
+       short mode,
+       short angle,
+       float resbuf,
+       struct Text* warptext
+       );
+
+       /// destructor
+       virtual ~KX_Dome (void);
+
+       //openGL checks:
+       bool    dlistSupported;
+
+       //openGL names:
+       GLuint domefacesId[7];          // ID of the images -- room for 7 images, using only 4 for 180º x 360º dome, 6 for panoramic and +1 for warp mesh
+       GLuint dlistId;                         // ID of the Display Lists of the images (used as an offset)
+       
+       typedef struct {
+               double u[3], v[3];
+               MT_Vector3 verts[3]; //three verts
+       } DomeFace;
+
+       //mesh warp functions
+       typedef struct {
+               double x, y, u, v, i;
+       } WarpMeshNode;
+
+       struct {
+               bool usemesh;
+               int mode;
+               int n_width, n_height; //nodes width and height
+               int imagewidth, imageheight;
+               int bufferwidth, bufferheight;
+               vector <vector <WarpMeshNode> > nodes;
+       } warp;
+
+       bool ParseWarpMesh(STR_String text);
+
+       vector <DomeFace> cubetop, cubebottom, cuberight, cubeleft, cubefront, cubeback; //for fisheye
+       vector <DomeFace> cubeleftback, cuberightback; //for panorama
+       
+       int nfacestop, nfacesbottom, nfacesleft, nfacesright, nfacesfront, nfacesback;
+       int nfacesleftback, nfacesrightback;
+
+       int GetNumberRenders(){return m_numfaces;};
+
+       void RenderDome(void);
+       void RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i);
+       void BindImages(int i);
+
+       void SetViewPort(GLuint viewport[4]);
+       void CalculateFrustum(KX_Camera* cam);
+       void RotateCamera(KX_Camera* cam, int i);
+
+       //Mesh  Creating Functions
+       void CreateMeshDome180(void);
+       void CreateMeshDome250(void);
+       void CreateMeshPanorama(void);
+
+       void SplitFace(vector <DomeFace>& face, int *nfaces);
+
+       void FlattenDome(MT_Vector3 verts[3]);
+       void FlattenPanorama(MT_Vector3 verts[3]);
+
+       //Draw functions
+       void GLDrawTriangles(vector <DomeFace>& face, int nfaces);
+       void GLDrawWarpQuads(void);
+       void Draw(void);
+       void DrawDomeFisheye(void);
+       void DrawPanorama(void);
+       void DrawDomeWarped(void);
+
+       //setting up openGL
+       void CreateGLImages(void);
+       void ClearGLImages(void);//called on resize
+       bool CreateDL(void); //create Display Lists
+       void ClearDL(void);  //remove Display Lists 
+
+       void CalculateCameraOrientation();
+       void CalculateImageSize(); //set m_imagesize
+
+       int canvaswidth;
+       int canvasheight;
+
+protected:
+       int m_drawingmode;
+
+       int m_imagesize;
+       int m_buffersize;       // canvas small dimension
+       int m_numfaces;         // 4 to 6 depending on the kind of dome image
+       int m_numimages;        //numfaces +1 if we have warp mesh
+       
+       float m_size;           // size to adjust
+       short m_resolution;     //resolution to tesselate the mesh
+       short m_mode;           // the mode (truncated, warped, panoramic,...)
+       short m_angle;          //the angle of the fisheye
+       float m_radangle;       //the angle of the fisheye in radians
+       float m_resbuffer;      //the resolution of the buffer
+       
+       RAS_Rect m_viewport;
+
+       MT_Matrix4x4 m_projmat;
+
+       MT_Matrix3x3 m_locRot [6];// the rotation matrix
+
+       /// rendered scene
+       KX_Scene * m_scene;
+
+    /// canvas
+    RAS_ICanvas* m_canvas;
+    /// rasterizer
+    RAS_IRasterizer* m_rasterizer;
+    /// render tools
+    RAS_IRenderTools* m_rendertools;
+    /// engine
+    KX_KetsjiEngine* m_engine;
+};
+
+#endif
\ No newline at end of file
index 70ae0e4b937d96c8573fb558d2e3ebdff5fa8333..e64ffa95161018ddcf0eb65cefae422f8cb9413a 100644 (file)
@@ -55,6 +55,7 @@
 #include "KX_Scene.h"
 #include "MT_CmMatrix4x4.h"
 #include "KX_Camera.h"
+#include "KX_Dome.h"
 #include "KX_Light.h"
 #include "KX_PythonInit.h"
 #include "KX_PyConstraintBinding.h"
@@ -144,6 +145,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
        m_stereo(false),
        m_curreye(0),
 
+       m_usedome(false),
+
        m_logger(NULL),
        
        // Set up timing info display variables
@@ -179,6 +182,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
 KX_KetsjiEngine::~KX_KetsjiEngine()
 {
        delete m_logger;
+       if(m_usedome)
+               delete m_dome;
 }
 
 
@@ -256,7 +261,124 @@ void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
        m_sceneconverter = sceneconverter;
 }
 
+void KX_KetsjiEngine::InitDome(float size, short res, short mode, short angle, float resbuf, struct Text* text)
+{
+       m_dome = new KX_Dome(m_canvas, m_rasterizer, m_rendertools,this, size, res, mode, angle, resbuf, text);
+       m_usedome = true;
+}
+
+void KX_KetsjiEngine::RenderDome()
+{
+       GLuint  viewport[4]={0};
+       glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
+//     unsigned int m_viewport[4] = {viewport[0], viewport[1], viewport[2], viewport[3]};
+       
+       m_dome->SetViewPort(viewport);
+
+       KX_Scene* firstscene = *m_scenes.begin();
+       const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
+
+       m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+
+       // hiding mouse cursor each frame
+       // (came back when going out of focus and then back in again)
+       if (m_hideCursor)
+               m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
+
+       // clear the entire game screen with the border color
+       // only once per frame
+
+       m_canvas->BeginDraw();
+
+       // BeginFrame() sets the actual drawing area. You can use a part of the window
+       if (!BeginFrame())
+               return;
+
+       int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
+       KX_SceneList::iterator sceneit;
+       for (int i=0;i<n_renders;i++){
+               m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
+               for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
+               // for each scene, call the proceed functions
+               {
+                       KX_Scene* scene = *sceneit;
+                       KX_Camera* cam = scene->GetActiveCamera();
+
+                       m_rendertools->BeginFrame(m_rasterizer);
+                       // pass the scene's worldsettings to the rasterizer
+                       SetWorldSettings(scene->GetWorldInfo());
+
+                       // shadow buffers
+                       if (i == 0){
+                               RenderShadowBuffers(scene);
+                               scene->UpdateMeshTransformations();//I need to run it somewherelse, otherwise Im overrunning it
+                       }
+                       // Avoid drawing the scene with the active camera twice when it's viewport is enabled
+                       if(cam && !cam->GetViewport())
+                       {
+                               if (scene->IsClearingZBuffer())
+                                       m_rasterizer->ClearDepthBuffer();
+               
+                               m_rendertools->SetAuxilaryClientInfo(scene);
+               
+                               // do the rendering
+                               m_dome->RenderDomeFrame(scene,cam, i);
+                       }
+                       
+                       list<class KX_Camera*>* cameras = scene->GetCameras();
+                       
+                       // Draw the scene once for each camera with an enabled viewport
+                       list<KX_Camera*>::iterator it = cameras->begin();
+                       while(it != cameras->end())
+                       {
+                               if((*it)->GetViewport())
+                               {
+                                       if (scene->IsClearingZBuffer())
+                                               m_rasterizer->ClearDepthBuffer();
+                       
+                                       m_rendertools->SetAuxilaryClientInfo(scene);
+                       
+                                       // do the rendering
+                                       m_dome->RenderDomeFrame(scene, (*it),i);
+                               }
+                               
+                               it++;
+                       }
+               }
+               m_dome->BindImages(i);
+       }       
+
+//     m_dome->Dome_PostRender(scene, cam, stereomode);
+       m_canvas->EndFrame();//XXX do we really need that?
+
+       m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
+
+       if (m_overrideFrameColor) //XXX why do we want
+       {
+               // Do not use the framing bar color set in the Blender scenes
+               m_canvas->ClearColor(
+                       m_overrideFrameColorR,
+                       m_overrideFrameColorG,
+                       m_overrideFrameColorB,
+                       1.0
+                       );
+       }
+       else
+       {
+               // Use the framing bar color set in the Blender scenes
+               m_canvas->ClearColor(
+                       framesettings.BarRed(),
+                       framesettings.BarGreen(),
+                       framesettings.BarBlue(),
+                       1.0
+                       );
+       }
+
+       m_dome->Draw();
 
+       //run 2dfilters
+       EndFrame();
+}
 
 /**
  * Ketsji Init(), Initializes datastructures and converts data from
@@ -631,6 +753,10 @@ else
 
 void KX_KetsjiEngine::Render()
 {
+       if(m_usedome){
+               RenderDome();
+               return;
+       }
        KX_Scene* firstscene = *m_scenes.begin();
        const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
 
@@ -1699,4 +1825,3 @@ void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
 }
 
 
-
index 8516049f6d86c11df33db936cd61831e137c7589..a8ccd6100d7c560b69494728ccb36879f41fd970 100644 (file)
@@ -74,6 +74,7 @@ private:
        PyObject*                                       m_pythondictionary;
        class SCA_IInputDevice*                         m_keyboarddevice;
        class SCA_IInputDevice*                         m_mousedevice;
+       class KX_Dome*                                          m_dome; // dome stereo mode
 
        /** Lists of scenes scheduled to be removed at the end of the frame. */
        std::set<STR_String> m_removingScenes;
@@ -208,6 +209,12 @@ public:
        RAS_ICanvas*                GetCanvas(){return m_canvas;};
        RAS_IRenderTools*           GetRenderTools(){return m_rendertools;};
 
+       /// Dome functions
+       void                    InitDome(float size, short res, short mode, short angle, float resbuf, struct Text* text); 
+       void                    EndDome();
+       void                    RenderDome();
+       bool                    m_usedome;
+
        ///returns true if an update happened to indicate -> Render
        bool                    NextFrame();
        void                    Render();
@@ -234,6 +241,8 @@ public:
        void                    GetSceneViewport(KX_Scene* scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport);
 
        void SetDrawType(int drawingtype);
+       int  GetDrawType(){return m_drawingmode;};
+
        void SetCameraZoom(float camzoom);
        
        void EnableCameraOverride(const STR_String& forscene);
index 83adcfd8321853b3c7bd7003485525c6ee5c040f..cfeda06e670d32fbd4075fdbe610b0f616f0af2f 100644 (file)
@@ -113,6 +113,7 @@ public:
                        RAS_STEREO_ANAGLYPH,
                        RAS_STEREO_SIDEBYSIDE,
                        RAS_STEREO_VINTERLACE,
+                       RAS_STEREO_DOME,
                        
                        RAS_STEREO_MAXSTEREO
        };
index 765ff0174eeeeadf4001d87ef568a5e601e63cbd..1a9a28916de1c1794fe37029cd6813c81517eea2 100644 (file)
@@ -436,7 +436,7 @@ RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
 
 bool RAS_OpenGLRasterizer::Stereo()
 {
-       if(m_stereomode == RAS_STEREO_NOSTEREO)
+       if(m_stereomode == RAS_STEREO_NOSTEREO || m_stereomode == RAS_STEREO_DOME)
                return false;
        else
                return true;
@@ -803,7 +803,7 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
        double mat[16];
 
        // correction for stereo
-       if(m_stereomode != RAS_STEREO_NOSTEREO)
+       if(Stereo())
        {
                        float near_div_focallength;
                        // next 2 params should be specified on command line and in Blender publisher
@@ -846,7 +846,7 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto
        m_viewmatrix = mat;
 
        // correction for stereo
-       if(m_stereomode != RAS_STEREO_NOSTEREO)
+       if(Stereo())
        {
                MT_Matrix3x3 camOrientMat3x3(camOrientQuat);
                MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention