Patch #18462: Fisheye (Dome) and Spherical Panoramic mode in BGE.
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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
1820
source/gameengine/Ketsji/KX_Dome.cpp
Normal file
1820
source/gameengine/Ketsji/KX_Dome.cpp
Normal file
@@ -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<63>t<EFBFBD> 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<38> 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<32> 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<38> 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<33>) 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<33>) 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<36>)
|
||||
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<39> 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<39>, 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<38>
|
||||
Uses 5 cameras for angles up to 250<35>
|
||||
Uses 6 cameras for angles up to 360<36>
|
||||
*/
|
||||
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<39> - Top
|
||||
c, -s, 0.0,
|
||||
0.0,0.0, -1.0,
|
||||
s, c, 0.0);
|
||||
|
||||
m_locRot[1] = MT_Matrix3x3( // 90<39> - Bottom
|
||||
-s, c, 0.0,
|
||||
0.0,0.0, 1.0,
|
||||
s, c, 0.0);
|
||||
|
||||
m_locRot[2] = MT_Matrix3x3( // 45<34> - Left
|
||||
c, 0.0, s,
|
||||
0, 1.0, 0.0,
|
||||
-s, 0.0, c);
|
||||
|
||||
m_locRot[3] = MT_Matrix3x3( // 45<34> - 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<39> - 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<39> - 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<39> - 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<39> - 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<38> - 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<34> - Left
|
||||
-s, 0.0, c,
|
||||
0, 1.0, 0.0,
|
||||
-c, 0.0, -s);
|
||||
|
||||
m_locRot[3] = MT_Matrix3x3( // 45<34> - Right
|
||||
c, 0.0, s,
|
||||
0, 1.0, 0.0,
|
||||
-s, 0.0, c);
|
||||
|
||||
m_locRot[4] = MT_Matrix3x3( // 135<33> - LeftBack
|
||||
-s, 0.0, -c,
|
||||
0.0, 1.0, 0.0,
|
||||
c, 0.0, -s);
|
||||
|
||||
m_locRot[5] = MT_Matrix3x3( // 135<33> - 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<34> (left)
|
||||
glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
|
||||
GLDrawTriangles(cubeleft, nfacesleft);
|
||||
|
||||
// domefacesId[2] => 45<34> (right)
|
||||
glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
|
||||
GLDrawTriangles(cuberight, nfacesright);
|
||||
|
||||
// domefacesId[0] => -135<33> (leftback)
|
||||
glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
|
||||
GLDrawTriangles(cubeleftback, nfacesleftback);
|
||||
|
||||
// domefacesId[3] => 135<33> (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);
|
||||
}
|
||||
183
source/gameengine/Ketsji/KX_Dome.h
Normal file
183
source/gameengine/Ketsji/KX_Dome.h
Normal file
@@ -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<63>t<EFBFBD> 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<38> x 360<36> 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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -113,6 +113,7 @@ public:
|
||||
RAS_STEREO_ANAGLYPH,
|
||||
RAS_STEREO_SIDEBYSIDE,
|
||||
RAS_STEREO_VINTERLACE,
|
||||
RAS_STEREO_DOME,
|
||||
|
||||
RAS_STEREO_MAXSTEREO
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user