blender/source/gameengine/Ketsji/KX_Dome.cpp

2053 lines
54 KiB
C++
Raw Normal View History

/*
* ***** BEGIN GPL LICENSE BLOCK *****
2012-03-09 18:28:30 +00:00
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
2012-03-09 18:28:30 +00:00
*
* 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 General Public License for more details.
2012-03-09 18:28:30 +00:00
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2012-03-09 18:28:30 +00:00
*
* 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.
*
* ***** END GPL LICENSE BLOCK *****
2012-03-09 18:28:30 +00:00
*/
/** \file gameengine/Ketsji/KX_Dome.cpp
* \ingroup ketsji
*/
#include "KX_Dome.h"
#ifdef WITH_PYTHON
#include <structmember.h>
#endif
#include <float.h>
#include <math.h>
#include "DNA_scene_types.h"
#include "RAS_CameraData.h"
#include "BLI_math.h"
#include "GL/glew.h"
// constructor
KX_Dome::KX_Dome (
2011-09-01 02:12:53 +00:00
RAS_ICanvas* canvas,
/// rasterizer
RAS_IRasterizer* rasterizer,
/// render tools
RAS_IRenderTools* rendertools,
/// engine
KX_KetsjiEngine* engine,
short res, //resolution of the mesh
short mode, //mode - fisheye, truncated, warped, panoramic, ...
short angle,
float resbuf, //size adjustment of the buffer
short tilt,
struct Text* warptext
):
dlistSupported(false),
canvaswidth(-1), canvasheight(-1),
m_drawingmode(engine->GetDrawType()),
m_resolution(res),
m_mode(mode),
m_angle(angle),
m_resbuffer(resbuf),
m_tilt(tilt),
m_canvas(canvas),
m_rasterizer(rasterizer),
m_rendertools(rendertools),
m_engine(engine)
{
warp.usemesh = false;
fboSupported = 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
const int *viewport = m_canvas->GetViewPort();
SetViewPort(viewport);
switch (m_mode) {
case DOME_FISHEYE:
2012-03-28 05:03:24 +00:00
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_ENVMAP:
m_angle = 360;
m_numfaces = 6;
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;
default: //DOME_TRUNCATED_FRONT and DOME_TRUNCATED_REAR
2012-03-28 05:03:24 +00:00
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;
}
m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces);
CalculateCameraOrientation();
CreateGLImages();
if (warp.usemesh)
fboSupported = CreateFBO();
dlistSupported = CreateDL();
}
// destructor
KX_Dome::~KX_Dome (void)
{
ClearGLImages();
if (fboSupported)
glDeleteFramebuffersEXT(1, &warp.fboId);
if (dlistSupported)
glDeleteLists(dlistId, (GLsizei) m_numimages);
}
void KX_Dome::SetViewPort(const int viewport[4])
{
if (canvaswidth != m_viewport.GetWidth() || canvasheight != m_viewport.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);
2012-03-28 05:03:24 +00:00
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, NULL);
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);
}
2012-03-28 05:03:24 +00:00
if (warp.usemesh) {
glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagesize, warp.imagesize, 0, GL_RGB8,
GL_UNSIGNED_BYTE, NULL);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagesize, warp.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);
}
}
void KX_Dome::ClearGLImages(void)
{
glDeleteTextures(m_numimages, (GLuint*)&domefacesId);
2012-03-09 18:28:30 +00:00
#if 0
for (int i=0;i<m_numimages;i++)
if (glIsTexture(domefacesId[i]))
glDeleteTextures(1, (GLuint*)&domefacesId[i]);
2012-03-09 18:28:30 +00:00
#endif
}
void KX_Dome::CalculateImageSize(void)
{
2012-03-09 18:28:30 +00:00
/*
* - determine the minimum buffer size
2012-03-18 07:38:51 +00:00
* - reduce the buffer for better performance
2012-03-09 18:28:30 +00:00
* - 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 = (int)(m_buffersize*m_resbuffer); //reduce buffer size for better performance
int i = 0;
while ((1 << i) <= m_buffersize)
i++;
m_imagesize = (1 << i);
2012-03-28 05:03:24 +00:00
if (warp.usemesh) {
// warp FBO needs to be up to twice as big as m_buffersize to get more resolution
warp.imagesize = m_imagesize;
if (m_buffersize == m_imagesize)
warp.imagesize *= 2;
//if FBO is not working/supported, we use the canvas dimension as buffer
warp.bufferwidth = canvaswidth;
warp.bufferheight = canvasheight;
}
}
bool KX_Dome::CreateDL()
{
dlistId = glGenLists((GLsizei) m_numimages);
if (dlistId != 0) {
2012-03-28 05:03:24 +00:00
if (m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED_FRONT || m_mode == DOME_TRUNCATED_REAR) {
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();
2012-03-28 05:03:24 +00:00
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();
}
2012-03-28 05:03:24 +00:00
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;
}
bool KX_Dome::CreateFBO(void)
{
if (!GLEW_EXT_framebuffer_object)
{
printf("Dome Error: FrameBuffer unsupported. Using low resolution warp image.");
return false;
}
glGenFramebuffersEXT(1, &warp.fboId);
if (warp.fboId==0)
{
printf("Dome Error: Invalid frame buffer object. Using low resolution warp image.");
return false;
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, domefacesId[m_numfaces], 0);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status == GL_FRAMEBUFFER_UNSUPPORTED_EXT)
{
printf("Dome Error: FrameBuffer settings unsupported. Using low resolution warp image.");
return false;
}
else if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
glDeleteFramebuffersEXT(1, &warp.fboId);
return false;
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
//nothing failed: we can use the whole FBO as buffersize
warp.bufferwidth = warp.bufferheight = warp.imagesize;
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) / warp.imagesize;
float uv_height = (float)(warp.bufferheight) / warp.imagesize;
2012-03-28 05:03:24 +00:00
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+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);
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+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][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);
}
}
glEnd();
}
2012-03-28 05:03:24 +00:00
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();
2012-06-06 22:38:39 +00:00
}
else {
printf("Dome Error: Warp Mode %d unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n", warp.mode);
}
}
bool KX_Dome::ParseWarpMesh(STR_String text)
{
2012-03-09 18:28:30 +00:00
/*
* //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
2013-06-25 22:58:23 +00:00
* The next line has the mesh dimensions
2012-03-09 18:28:30 +00:00
* Rest of the lines are the nodes of the mesh. Each line has x y u v i
* (x,y) are the normalized screen coordinates
2012-03-09 18:28:30 +00:00
* (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;
int nodeX=0, nodeY=0;
vector<STR_String> columns, lines;
lines = text.Explode('\n');
2012-03-28 05:03:24 +00:00
if (lines.size() < 6) {
printf("Dome Error: Warp Mesh File with insufficient data!\n");
return false;
}
columns = lines[1].Explode(' ');
if (columns.size() == 1)
columns = lines[1].Explode('\t');
2012-03-28 05:03:24 +00:00
if (columns.size() !=2) {
printf("Dome 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]);
2012-03-28 05:03:24 +00:00
if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)) {
printf("Dome Error: Warp Mesh File with insufficient data!\n");
return false;
2012-06-06 22:38:39 +00:00
}
else {
warp.nodes = vector<vector<WarpMeshNode> > (warp.n_height, vector<WarpMeshNode>(warp.n_width));
2012-03-28 05:03:24 +00:00
for (i=2; i-2 < (warp.n_width*warp.n_height); i++) {
columns = lines[i].Explode(' ');
if (columns.size() == 1)
columns = lines[i].Explode('\t');
2012-03-28 05:03:24 +00:00
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]);
}
2012-06-06 22:38:39 +00:00
else {
warp.nodes.clear();
printf("Dome 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)
{
2012-03-09 18:28:30 +00:00
/*
* 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 uv_ratio = (float)(m_buffersize-1) / m_imagesize;
m_radangle = DEG2RADF(m_angle); //calculates the radians angle, used for flattening
2010-09-30 07:06:00 +00:00
//creating faces for the env mapcube 180deg Dome
// Top Face - just a triangle
2010-09-30 07:06:00 +00:00
cubetop[0].verts[0][0] = -M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cubetop[0].verts[1][1] = M_SQRT2 / 2.0;
cubetop[0].verts[1][2] = 0.5;
cubetop[0].u[1] = 0.0;
cubetop[0].v[1] = 0.0;
2010-09-30 07:06:00 +00:00
cubetop[0].verts[2][0] = M_SQRT2 / 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 */
2010-09-30 07:06:00 +00:00
cubebottom[0].verts[0][0] = -M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cubebottom[0].verts[1][0] = M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cubebottom[0].verts[2][1] = M_SQRT2 / 2.0;
cubebottom[0].verts[2][2] = -0.5;
cubebottom[0].u[2] = 0.0;
cubebottom[0].v[2] = 0.0;
2012-09-16 04:58:18 +00:00
nfacesbottom = 1;
/* Left face - two triangles */
2010-09-30 07:06:00 +00:00
cubeleft[0].verts[0][0] = -M_SQRT2 / 2.0;
cubeleft[0].verts[0][1] = 0.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;
2010-09-30 07:06:00 +00:00
cubeleft[0].verts[1][1] = M_SQRT2 / 2.0;
cubeleft[0].verts[1][2] = -0.5;
cubeleft[0].u[1] = uv_ratio;
cubeleft[0].v[1] = 0.0;
2010-09-30 07:06:00 +00:00
cubeleft[0].verts[2][0] = -M_SQRT2 / 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
2010-09-30 07:06:00 +00:00
cubeleft[1].verts[0][0] = -M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cubeleft[1].verts[1][1] = M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cubeleft[1].verts[2][1] = M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cuberight[0].verts[0][1] = M_SQRT2 / 2.0;
cuberight[0].verts[0][2] = -0.5;
cuberight[0].u[0] = 0.0;
cuberight[0].v[0] = 0.0;
2010-09-30 07:06:00 +00:00
cuberight[0].verts[1][0] = M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cuberight[0].verts[2][0] = M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cuberight[1].verts[0][1] = M_SQRT2 / 2.0;
cuberight[1].verts[0][2] = -0.5;
cuberight[1].u[0] = 0.0;
cuberight[1].v[0] = 0.0;
2010-09-30 07:06:00 +00:00
cuberight[1].verts[1][0] = M_SQRT2 / 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;
2010-09-30 07:06:00 +00:00
cuberight[1].verts[2][1] = M_SQRT2 / 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
2012-03-28 05:03:24 +00:00
for (i=0;i<m_resolution;i++) {
cubetop.resize(4*nfacestop);
SplitFace(cubetop,&nfacestop);
cubebottom.resize(4*nfacesbottom);
2012-09-16 04:58:18 +00:00
SplitFace(cubebottom,&nfacesbottom);
cubeleft.resize(4*nfacesleft);
SplitFace(cubeleft,&nfacesleft);
cuberight.resize(4*nfacesright);
SplitFace(cuberight,&nfacesright);
2012-09-16 04:58:18 +00:00
}
// Turn into a hemisphere
2012-03-28 05:03:24 +00:00
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)
{
2012-03-09 18:28:30 +00:00
/*
* 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
2012-03-09 18:28:30 +00:00
/*
* 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 220deg domes) we don't need to create and tessellate the whole cube.
* Therefore the lateral cube faces could be small, and the tessellate mesh would be completely used.
2012-03-18 07:38:51 +00:00
* (if we always worked with verts_height = 1.0, we would be discarding a lot of the calculated and tessellated geometry).
2012-03-09 18:28:30 +00:00
*
* 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 length 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 = tanf((rad_ang / 2.0f) - (float)(MT_PI / 2.0)) * (float)M_SQRT2;
uv_height = uv_ratio * ( (verts_height / 2.0f) + 0.5f);
uv_base = uv_ratio * (1.0 - ((verts_height / 2.0f) + 0.5f));
2010-09-30 07:06:00 +00:00
//creating faces for the env mapcube 180deg 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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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;
2012-09-16 04:58:18 +00:00
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!
2012-03-28 05:03:24 +00:00
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);
2012-09-16 04:58:18 +00:00
SplitFace(cubebottom,&nfacesbottom);
cubeleft.resize(4*nfacesleft);
SplitFace(cubeleft,&nfacesleft);
cuberight.resize(4*nfacesright);
SplitFace(cuberight,&nfacesright);
}
// Turn into a hemisphere/sphere
2012-03-28 05:03:24 +00:00
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++)
2012-09-16 04:58:18 +00:00
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++)
2012-09-16 04:58:18 +00:00
FlattenDome(cubeleft[i].verts);
for (i=0;i<nfacesright;i++)
FlattenDome(cuberight[i].verts);
}
void KX_Dome::CreateMeshPanorama(void)
{
2012-03-09 18:28:30 +00:00
/*
* 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 uv_ratio = (float)(m_buffersize-1) / m_imagesize;
/* Top face - two triangles */
2010-09-30 07:06:00 +00:00
cubetop[0].verts[0][0] = -M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubetop[0].verts[1][1] = M_SQRT2;
cubetop[0].verts[1][2] = 1.0;
cubetop[0].u[1] = 0.0;
cubetop[0].v[1] = 0.0;
//second triangle
2010-09-30 07:06:00 +00:00
cubetop[0].verts[2][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubetop[1].verts[0][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubetop[1].verts[1][1] = -M_SQRT2;
cubetop[1].verts[1][2] = 1.0;
cubetop[1].u[1] = uv_ratio;
cubetop[1].v[1] = uv_ratio;
2010-09-30 07:06:00 +00:00
cubetop[1].verts[2][0] = -M_SQRT2;
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 */
2010-09-30 07:06:00 +00:00
cubebottom[0].verts[0][0] = -M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubebottom[0].verts[1][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubebottom[0].verts[2][1] = M_SQRT2;
cubebottom[0].verts[2][2] = -1.0;
cubebottom[0].u[2] = 0.0;
cubebottom[0].v[2] = 0.0;
//second triangle
2010-09-30 07:06:00 +00:00
cubebottom[1].verts[0][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubebottom[1].verts[1][0] = -M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubebottom[1].verts[2][1] = -M_SQRT2;
cubebottom[1].verts[2][2] = -1.0;
cubebottom[1].u[2] = uv_ratio;
cubebottom[1].v[2] = uv_ratio;
nfacesbottom = 2;
2010-09-30 07:06:00 +00:00
/* Left Back (135deg) face - two triangles */
cubeleftback[0].verts[0][0] = 0;
2010-09-30 07:06:00 +00:00
cubeleftback[0].verts[0][1] = -M_SQRT2;
cubeleftback[0].verts[0][2] = -1.0;
cubeleftback[0].u[0] = 0;
cubeleftback[0].v[0] = 0;
2010-09-30 07:06:00 +00:00
cubeleftback[0].verts[1][0] = -M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubeleftback[0].verts[2][1] = -M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubeleftback[1].verts[0][1] = -M_SQRT2;
cubeleftback[1].verts[0][2] = 1.0;
cubeleftback[1].u[0] = 0;
cubeleftback[1].v[0] = uv_ratio;
2010-09-30 07:06:00 +00:00
cubeleftback[1].verts[1][0] = -M_SQRT2;
cubeleftback[1].verts[1][1] = 0;
cubeleftback[1].verts[1][2] = -1.0;
cubeleftback[1].u[1] = uv_ratio;
cubeleftback[1].v[1] = 0;
2010-09-30 07:06:00 +00:00
cubeleftback[1].verts[2][0] = -M_SQRT2;
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 */
2010-09-30 07:06:00 +00:00
cubeleft[0].verts[0][0] = -M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubeleft[0].verts[1][1] = M_SQRT2;
cubeleft[0].verts[1][2] = -1.0;
cubeleft[0].u[1] = uv_ratio;
cubeleft[0].v[1] = 0;
2010-09-30 07:06:00 +00:00
cubeleft[0].verts[2][0] = -M_SQRT2;
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
2010-09-30 07:06:00 +00:00
cubeleft[1].verts[0][0] = -M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cubeleft[1].verts[1][1] = M_SQRT2;
cubeleft[1].verts[1][2] = -1.0;
cubeleft[1].u[1] = uv_ratio;
cubeleft[1].v[1] = 0;
cubeleft[1].verts[2][0] = 0;
2010-09-30 07:06:00 +00:00
cubeleft[1].verts[2][1] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cuberight[0].verts[0][1] = M_SQRT2;
cuberight[0].verts[0][2] = -1.0;
cuberight[0].u[0] = 0;
cuberight[0].v[0] = 0;
2010-09-30 07:06:00 +00:00
cuberight[0].verts[1][0] = M_SQRT2;
cuberight[0].verts[1][1] = 0;
cuberight[0].verts[1][2] = -1.0;
cuberight[0].u[1] = uv_ratio;
cuberight[0].v[1] = 0;
2010-09-30 07:06:00 +00:00
cuberight[0].verts[2][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cuberight[1].verts[0][1] = M_SQRT2;
cuberight[1].verts[0][2] = -1.0;
cuberight[1].u[0] = 0;
cuberight[1].v[0] = 0;
2010-09-30 07:06:00 +00:00
cuberight[1].verts[1][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cuberight[1].verts[2][1] = M_SQRT2;
cuberight[1].verts[2][2] = 1.0;
cuberight[1].u[2] = 0;
cuberight[1].v[2] = uv_ratio;
nfacesright = 2;
2010-09-30 07:06:00 +00:00
/* Right Back (-135deg) face - two triangles */
cuberightback[0].verts[0][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cuberightback[0].verts[1][1] = -M_SQRT2;
cuberightback[0].verts[1][2] = -1.0;
cuberightback[0].u[1] = uv_ratio;
cuberightback[0].v[1] = 0;
cuberightback[0].verts[2][0] = 0;
2010-09-30 07:06:00 +00:00
cuberightback[0].verts[2][1] = -M_SQRT2;
cuberightback[0].verts[2][2] = 1.0;
cuberightback[0].u[2] = uv_ratio;
cuberightback[0].v[2] = uv_ratio;
//second triangle
2010-09-30 07:06:00 +00:00
cuberightback[1].verts[0][0] = M_SQRT2;
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;
2010-09-30 07:06:00 +00:00
cuberightback[1].verts[1][1] = -M_SQRT2;
cuberightback[1].verts[1][2] = 1.0;
cuberightback[1].u[1] = uv_ratio;
cuberightback[1].v[1] = uv_ratio;
2010-09-30 07:06:00 +00:00
cuberightback[1].verts[2][0] = M_SQRT2;
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;
2012-03-28 05:03:24 +00:00
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 /= (double)this->m_radangle / 2.0;
phi = atan2(verts[i][2], verts[i][0]);
verts[i][0] = r * cos(phi);
verts[i][1] = 0;
verts[i][2] = r * sin(phi);
2012-03-28 05:03:24 +00:00
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])
{
2010-09-30 07:06:00 +00:00
// it creates a full spherical panoramic (360deg)
int i;
double phi, theta;
bool edge=false;
2012-03-28 05:03:24 +00:00
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;
theta = asin(verts[i][2]);
verts[i][2] = theta / MT_PI;
}
2012-03-28 05:03:24 +00:00
if (edge) {
bool right=false;
2012-03-28 05:03:24 +00:00
for (i=0;i<3;i++) {
if (fmod(verts[i][0],1.0) > 0.0) {
right=true;
break;
}
}
2012-03-28 05:03:24 +00:00
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;
2012-03-28 05:03:24 +00:00
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;
2012-09-16 04:58:18 +00:00
face[n2+2].v[2] = (face[i].v[2] + face[i].v[0]) /2;
2012-02-27 10:35:39 +00:00
//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;
2012-02-27 10:35:39 +00:00
//face[i].v[0] = face[i].v[0];
face[i].v[1] = (face[i].v[0] + face[i].v[1]) /2;
2012-09-16 04:58:18 +00:00
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)
{
2012-03-09 18:28:30 +00:00
#if 0
2010-09-30 07:06:00 +00:00
// manually creating a 90deg Field of View Frustum
2012-03-09 18:28:30 +00:00
// 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());
2012-03-09 18:28:30 +00:00
#endif
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;
2010-09-30 07:06:00 +00:00
float top = m_frustrum.camnear; // for deg = 90deg, 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()
{
/*
2012-03-09 18:28:30 +00:00
* Uses 4 cameras for angles up to 180deg
* Uses 5 cameras for angles up to 250deg
* Uses 6 cameras for angles up to 360deg
*/
int i;
float deg45 = MT_PI / 4;
MT_Scalar c = cos(deg45);
MT_Scalar s = sin(deg45);
if (m_angle <= 180 && (m_mode == DOME_FISHEYE
|| m_mode == DOME_TRUNCATED_FRONT
2012-03-28 05:03:24 +00:00
|| m_mode == DOME_TRUNCATED_REAR)) {
2010-09-30 07:06:00 +00:00
m_locRot[0] = MT_Matrix3x3( // 90deg - Top
c, -s, 0.0,
0.0,0.0, -1.0,
s, c, 0.0);
2010-09-30 07:06:00 +00:00
m_locRot[1] = MT_Matrix3x3( // 90deg - Bottom
-s, c, 0.0,
0.0,0.0, 1.0,
s, c, 0.0);
2010-09-30 07:06:00 +00:00
m_locRot[2] = MT_Matrix3x3( // 45deg - Left
c, 0.0, s,
0, 1.0, 0.0,
-s, 0.0, c);
2010-09-30 07:06:00 +00:00
m_locRot[3] = MT_Matrix3x3( // 45deg - Right
c, 0.0, -s,
0.0, 1.0, 0.0,
s, 0.0, c);
} else if (m_mode == DOME_ENVMAP || (m_angle > 180 && (m_mode == DOME_FISHEYE
|| m_mode == DOME_TRUNCATED_FRONT
2012-03-28 05:03:24 +00:00
|| m_mode == DOME_TRUNCATED_REAR))) {
2010-09-30 07:06:00 +00:00
m_locRot[0] = MT_Matrix3x3( // 90deg - Top
1.0, 0.0, 0.0,
0.0, 0.0,-1.0,
0.0, 1.0, 0.0);
2010-09-30 07:06:00 +00:00
m_locRot[1] = MT_Matrix3x3( // 90deg - Bottom
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
0.0,-1.0, 0.0);
2010-09-30 07:06:00 +00:00
m_locRot[2] = MT_Matrix3x3( // -90deg - Left
0.0, 0.0, 1.0,
0.0, 1.0, 0.0,
-1.0, 0.0, 0.0);
2010-09-30 07:06:00 +00:00
m_locRot[3] = MT_Matrix3x3( // 90deg - Right
0.0, 0.0,-1.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0);
2010-09-30 07:06:00 +00:00
m_locRot[4] = MT_Matrix3x3( // 0deg - Front
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0);
2010-09-30 07:06:00 +00:00
m_locRot[5] = MT_Matrix3x3( // 180deg - Back - USED for ENVMAP only
-1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0,-1.0);
2012-03-28 05:03:24 +00:00
} 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);
2010-09-30 07:06:00 +00:00
m_locRot[2] = MT_Matrix3x3( // 45deg - Left
-s, 0.0, c,
0, 1.0, 0.0,
-c, 0.0, -s);
2010-09-30 07:06:00 +00:00
m_locRot[3] = MT_Matrix3x3( // 45deg - Right
c, 0.0, s,
0, 1.0, 0.0,
-s, 0.0, c);
2010-09-30 07:06:00 +00:00
m_locRot[4] = MT_Matrix3x3( // 135deg - LeftBack
-s, 0.0, -c,
0.0, 1.0, 0.0,
c, 0.0, -s);
2010-09-30 07:06:00 +00:00
m_locRot[5] = MT_Matrix3x3( // 135deg - RightBack
c, 0.0, -s,
0.0, 1.0, 0.0,
s, 0.0, c);
}
// rotating the camera in horizontal axis
if (m_tilt)
{
float tiltdeg = ((m_tilt % 360) * 2 * MT_PI) / 360;
c = cos(tiltdeg);
s = sin(tiltdeg);
MT_Matrix3x3 tilt_mat = MT_Matrix3x3(
1.0, 0.0, 0.0,
0.0, c, -s,
0.0, s, c
);
for (i =0;i<6;i++)
m_locRot[i] = tilt_mat * m_locRot[i];
}
}
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->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
cam->SetModelviewMatrix(viewmat);
// restore the original orientation
cam->NodeSetLocalOrientation(camori);
cam->NodeUpdateGS(0.f);
}
void KX_Dome::Draw(void)
{
2012-03-28 05:03:24 +00:00
if (fboSupported) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
glViewport(0,0,warp.imagesize, warp.imagesize);
glScissor(0,0,warp.imagesize, warp.imagesize);
}
switch (m_mode) {
case DOME_FISHEYE:
DrawDomeFisheye();
break;
case DOME_ENVMAP:
DrawEnvMap();
break;
case DOME_PANORAM_SPH:
DrawPanorama();
break;
case DOME_TRUNCATED_FRONT:
DrawDomeFisheye();
break;
case DOME_TRUNCATED_REAR:
DrawDomeFisheye();
break;
}
if (warp.usemesh)
{
if (fboSupported)
{
m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
else
{
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::DrawEnvMap(void)
{
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, (-0.66), 0.66, -20.0, 10.0); //stretch the image to reduce resolution lost
else {
2012-03-28 05:03:24 +00:00
if (can_width/3 <= can_height/2) {
ortho_width = 1.0;
ortho_height = (float)can_height/can_width;
2012-06-06 22:38:39 +00:00
}
else {
ortho_height = 2.0f / 3;
ortho_width = (float)can_width/can_height * ortho_height;
}
glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -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);
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_ratio = (float)(m_buffersize-1) / m_imagesize;
double onebythree = 1.0f / 3;
// domefacesId[0] => (top)
glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
glBegin(GL_QUADS);
glTexCoord2f(uv_ratio,uv_ratio);
glVertex3f( onebythree, 0.0f, 3.0f);
glTexCoord2f(0.0,uv_ratio);
glVertex3f(-onebythree, 0.0f, 3.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-onebythree,-2 * onebythree, 3.0f);
glTexCoord2f(uv_ratio,0.0);
glVertex3f(onebythree,-2 * onebythree, 3.0f);
glEnd();
// domefacesId[1] => (bottom)
glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
glBegin(GL_QUADS);
glTexCoord2f(uv_ratio,uv_ratio);
glVertex3f(-onebythree, 0.0f, 3.0f);
glTexCoord2f(0.0,uv_ratio);
glVertex3f(-1.0f, 0.0f, 3.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-1.0f,-2 * onebythree, 3.0f);
glTexCoord2f(uv_ratio,0.0);
glVertex3f(-onebythree,-2 * onebythree, 3.0f);
glEnd();
2010-09-30 07:06:00 +00:00
// domefacesId[2] => -90deg (left)
glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
glBegin(GL_QUADS);
glTexCoord2f(uv_ratio,uv_ratio);
glVertex3f(-onebythree, 2 * onebythree, 3.0f);
glTexCoord2f(0.0,uv_ratio);
glVertex3f(-1.0f, 2 * onebythree, 3.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-1.0f, 0.0f, 3.0f);
glTexCoord2f(uv_ratio,0.0);
glVertex3f(-onebythree, 0.0f, 3.0f);
glEnd();
2010-09-30 07:06:00 +00:00
// domefacesId[3] => 90deg (right)
glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
glBegin(GL_QUADS);
glTexCoord2f(uv_ratio,uv_ratio);
glVertex3f( 1.0f, 2 * onebythree, 3.0f);
glTexCoord2f(0.0,uv_ratio);
glVertex3f( onebythree, 2 * onebythree, 3.0f);
glTexCoord2f(0.0,0.0);
glVertex3f( onebythree, 0.0f, 3.0f);
glTexCoord2f(uv_ratio,0.0);
glVertex3f(1.0f, 0.0f, 3.0f);
glEnd();
2010-09-30 07:06:00 +00:00
// domefacesId[4] => 0deg (front)
glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
glBegin(GL_QUADS);
glTexCoord2f(uv_ratio,uv_ratio);
glVertex3f( 1.0f, 0.0f, 3.0f);
glTexCoord2f(0.0,uv_ratio);
glVertex3f( onebythree, 0.0f, 3.0f);
glTexCoord2f(0.0,0.0);
glVertex3f( onebythree,-2 * onebythree, 3.0f);
glTexCoord2f(uv_ratio,0.0);
glVertex3f(1.0f, -2 * onebythree, 3.0f);
glEnd();
2010-09-30 07:06:00 +00:00
// domefacesId[5] => 180deg (back)
glBindTexture(GL_TEXTURE_2D, domefacesId[5]);
glBegin(GL_QUADS);
glTexCoord2f(uv_ratio,uv_ratio);
glVertex3f( onebythree, 2 * onebythree, 3.0f);
glTexCoord2f(0.0,uv_ratio);
glVertex3f(-onebythree, 2 * onebythree, 3.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-onebythree, 0.0f, 3.0f);
glTexCoord2f(uv_ratio,0.0);
glVertex3f(onebythree, 0.0f, 3.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
}
void KX_Dome::DrawDomeFisheye(void)
{
int i;
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 (m_mode == DOME_FISHEYE) {
if (warp.usemesh)
glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost
else {
2012-03-28 05:03:24 +00:00
if (can_width < can_height) {
ortho_width = 1.0;
ortho_height = (float)can_height/can_width;
2012-06-06 22:38:39 +00:00
}
else {
ortho_width = (float)can_width/can_height;
ortho_height = 1.0;
}
glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
}
}
else if (m_mode == DOME_TRUNCATED_FRONT)
{
ortho_width = 1.0;
ortho_height = 2.0f * ((float)can_height / can_width) - 1.0f;
glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0);
}
else { //m_mode == DOME_TRUNCATED_REAR
ortho_width = 1.0;
ortho_height = 2.0f * ((float)can_height / can_width) - 1.0f;
glOrtho((-ortho_width), ortho_width, (-ortho_width), 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);
2012-03-28 05:03:24 +00:00
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);
2012-09-16 04:58:18 +00:00
// 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);
2012-03-28 05:03:24 +00:00
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;
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
2012-03-28 05:03:24 +00:00
if ((can_width / 2) <= (can_height)) {
ortho_width = 1.0;
ortho_height = (float)can_height/can_width;
2012-06-06 22:38:39 +00:00
}
else {
ortho_width = (float)can_width / can_height * 0.5f;
ortho_height = 0.5f;
}
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);
2012-03-28 05:03:24 +00:00
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);
2010-09-30 07:06:00 +00:00
// domefacesId[1] => -45deg (left)
glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
GLDrawTriangles(cubeleft, nfacesleft);
2010-09-30 07:06:00 +00:00
// domefacesId[2] => 45deg (right)
glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
GLDrawTriangles(cuberight, nfacesright);
2010-09-30 07:06:00 +00:00
// domefacesId[0] => -135deg (leftback)
glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
GLDrawTriangles(cubeleftback, nfacesleftback);
2010-09-30 07:06:00 +00:00
// domefacesId[3] => 135deg (rightback)
glBindTexture(GL_TEXTURE_2D, domefacesId[5]);
GLDrawTriangles(cuberightback, nfacesrightback);
}
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
}
void KX_Dome::DrawDomeWarped(void)
{
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();
2011-09-01 02:12:53 +00:00
double screen_ratio = can_width/ (double) can_height;
2011-09-01 02:12:53 +00:00
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);
2012-03-28 05:03:24 +00:00
if (dlistSupported) {
glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
glCallList(dlistId + m_numfaces);
}
2012-06-06 22:38:39 +00:00
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->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), 1.0);
cam->SetModelviewMatrix(viewmat);
// restore the original orientation
cam->NodeSetLocalOrientation(camori);
cam->NodeUpdateGS(0.f);
scene->CalculateVisibleMeshes(m_rasterizer,cam);
scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
}