forked from bartvdbraak/blender
ee7a2ccb22
The funny thing is: I only spotted this bug in March of this year. Almost one year after the original release. I think I don't parent objects to the camera often. In terms of code I think that I can even think in a more elegant solution. I don't really need to rotate the camera, but simply to calculate its Modelview Matrix. """ m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), 1.0); cam->SetModelviewMatrix(viewmat); """ The reason why I originally was rotating the camera was to make sure the frustum calculation was using the right camera frustum. For the frustum it takes the camera modelviewmatrix so the rotation really shouldn't be necessary. Leaving as it's for the time being. * Note: the bug was never officially reported
2060 lines
54 KiB
C++
2060 lines
54 KiB
C++
/* $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"
|
||
|
||
#ifndef DISABLE_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 (
|
||
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
|
||
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_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
|
||
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(GLuint 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);
|
||
|
||
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.imagesize, warp.imagesize, 0, GL_RGB8,
|
||
GL_UNSIGNED_BYTE, 0);
|
||
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);
|
||
/*
|
||
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
|
||
*/
|
||
/*
|
||
Blender handles Canvas size differently when in fullscreen mode.
|
||
We are manually checking for that. Although it's a hack, it works.
|
||
|
||
Bug reported here: #18655 - Inconsistency of pixels in canvas dimensions when in maximized mode (affecting BGE Dome)
|
||
http://projects.blender.org/tracker/?func=detail&aid=18655&group_id=9&atid=125
|
||
*/
|
||
|
||
canvaswidth = m_canvas->GetWidth();
|
||
canvasheight = m_canvas->GetHeight();
|
||
|
||
bool fullscreen(false); //XXX HACK
|
||
fullscreen = (canvaswidth != m_viewport.GetWidth());
|
||
|
||
m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth);
|
||
m_buffersize = (int)(m_buffersize*m_resbuffer); //reduce buffer size for better performance
|
||
|
||
if (fullscreen) //XXX HACK
|
||
m_buffersize --;
|
||
|
||
int i = 0;
|
||
while ((1 << i) <= m_buffersize)
|
||
i++;
|
||
m_imagesize = (1 << i);
|
||
|
||
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;
|
||
}
|
||
|
||
//XXX HACK
|
||
canvaswidth = m_viewport.GetWidth();
|
||
canvasheight = m_viewport.GetHeight();
|
||
}
|
||
|
||
bool KX_Dome::CreateDL(){
|
||
dlistId = glGenLists((GLsizei) m_numimages);
|
||
if (dlistId != 0) {
|
||
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();
|
||
|
||
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;
|
||
}
|
||
|
||
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;
|
||
|
||
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("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)
|
||
{
|
||
/*
|
||
//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;
|
||
int nodeX=0, nodeY=0;
|
||
|
||
vector<STR_String> columns, lines;
|
||
|
||
lines = text.Explode('\n');
|
||
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');
|
||
|
||
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]);
|
||
|
||
if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)){
|
||
printf("Dome 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() == 1)
|
||
columns = lines[i].Explode('\t');
|
||
|
||
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("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)
|
||
{
|
||
/*
|
||
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 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 = 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>
|
||
*/
|
||
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
|
||
|| m_mode == DOME_TRUNCATED_REAR)){
|
||
|
||
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_ENVMAP || (m_angle > 180 && (m_mode == DOME_FISHEYE
|
||
|| m_mode == DOME_TRUNCATED_FRONT
|
||
|| m_mode == DOME_TRUNCATED_REAR))){
|
||
|
||
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 - USED for ENVMAP only
|
||
-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);
|
||
}
|
||
|
||
// 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)
|
||
{
|
||
|
||
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 {
|
||
if (can_width/3 <= can_height/2){
|
||
ortho_width = 1.0;
|
||
ortho_height = (float)can_height/can_width;
|
||
}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();
|
||
|
||
// domefacesId[2] => -90<39> (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();
|
||
|
||
// domefacesId[3] => 90<39> (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();
|
||
|
||
// domefacesId[4] => 0<> (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();
|
||
|
||
// domefacesId[5] => 180<38> (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 {
|
||
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;
|
||
}
|
||
|
||
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 * ((float)can_height/can_width) - 1.0 ;
|
||
|
||
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 * ((float)can_height/can_width) - 1.0 ;
|
||
|
||
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);
|
||
|
||
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;
|
||
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;
|
||
}
|
||
|
||
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)
|
||
{
|
||
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;
|
||
|
||
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);
|
||
|
||
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->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);
|
||
}
|
||
|