Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj8
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/intern/scene.c16
-rw-r--r--source/blender/blenloader/intern/readfile.c26
-rw-r--r--source/blender/makesdna/DNA_scene_types.h9
-rw-r--r--source/blender/src/buttons_scene.c17
-rw-r--r--source/blender/src/header_text.c1
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp4
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp1820
-rw-r--r--source/gameengine/Ketsji/KX_Dome.h183
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp127
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h9
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h1
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp6
16 files changed, 2227 insertions, 9 deletions
diff --git a/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj b/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
index c425b5664ad..80c34bef223 100644
--- a/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
+++ b/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
@@ -514,6 +514,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\gameengine\Ketsji\KX_Dome.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\gameengine\Ketsji\KX_EmptyObject.cpp"
>
</File>
@@ -803,6 +807,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\gameengine\Ketsji\KX_Dome.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\gameengine\Ketsji\KX_EmptyObject.h"
>
</File>
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index db6d4762b17..d49a5425b61 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -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
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 2bd528ab8c8..2c3ef42c021 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -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
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 1727edc10fc..5def3577218 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -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
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index c2eaae011c8..06c8370bde2 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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)
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index b8a734b6e94..bf5b2ad3df5 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -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 */
diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c
index aa072285556..f026e5f4034 100644
--- a/source/blender/src/buttons_scene.c
+++ b/source/blender/src/buttons_scene.c
@@ -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;
diff --git a/source/blender/src/header_text.c b/source/blender/src/header_text.c
index 9268642db2f..050ff192df6 100644
--- a/source/blender/src/header_text.c
+++ b/source/blender/src/header_text.c
@@ -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);
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 1c91ad784ac..fee5a4ad899 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -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
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 3432d498981..6ff46ca8200 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -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
index 00000000000..4ab0f93f687
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -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
index 00000000000..de3360cd897
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Dome.h
@@ -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
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 70ae0e4b937..e64ffa95161 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -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
}
-
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 8516049f6d8..a8ccd6100d7 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -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);
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index 83adcfd8321..cfeda06e670 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -113,6 +113,7 @@ public:
RAS_STEREO_ANAGLYPH,
RAS_STEREO_SIDEBYSIDE,
RAS_STEREO_VINTERLACE,
+ RAS_STEREO_DOME,
RAS_STEREO_MAXSTEREO
};
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 765ff0174ee..1a9a28916de 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -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