/* $Id$ ----------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. Contributor(s): Dalai Felinto This code is originally inspired on some of the ideas and codes from Paul Bourke. Developed as part of a Research and Development project for SAT - La Société des arts technologiques. ----------------------------------------------------------------------------- */ #include "KX_Dome.h" #include #include #include #include "DNA_scene_types.h" #include "RAS_CameraData.h" #include "BLI_arithb.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, float size, //size for adjustments short res, //resolution of the mesh short mode, //mode - fisheye, truncated, warped, panoramic, ... short angle, float resbuf, //size adjustment of the buffer struct Text* warptext ): m_canvas(canvas), m_rasterizer(rasterizer), m_rendertools(rendertools), m_engine(engine), m_drawingmode(engine->GetDrawType()), m_size(size), m_resolution(res), m_mode(mode), m_angle(angle), m_resbuffer(resbuf), canvaswidth(-1), canvasheight(-1), dlistSupported(false) { warp.usemesh = false; if (mode >= DOME_NUM_MODES) m_mode = DOME_FISHEYE; if (warptext) // it there is a text data try to warp it { char *buf; buf = txt_to_buf(warptext); if (buf) { warp.usemesh = ParseWarpMesh(STR_String(buf)); MEM_freeN(buf); } } //setting the viewport size GLuint viewport[4]={0}; glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); SetViewPort(viewport); switch(m_mode){ case DOME_FISHEYE: if (m_angle <= 180){ cubetop.resize(1); cubebottom.resize(1); cubeleft.resize(2); cuberight.resize(2); CreateMeshDome180(); m_numfaces = 4; }else if (m_angle > 180){ cubetop.resize(2); cubebottom.resize(2); cubeleft.resize(2); cubefront.resize(2); cuberight.resize(2); CreateMeshDome250(); m_numfaces = 5; } break; case DOME_TRUNCATED: cubetop.resize(1); cubebottom.resize(1); cubeleft.resize(2); cuberight.resize(2); m_angle = 180; CreateMeshDome180(); m_numfaces = 4; break; case DOME_PANORAM_SPH: cubeleft.resize(2); cubeleftback.resize(2); cuberight.resize(2); cuberightback.resize(2); cubetop.resize(2); cubebottom.resize(2); m_angle = 360; CreateMeshPanorama(); m_numfaces = 6; break; } m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces); CalculateCameraOrientation(); CreateGLImages(); dlistSupported = CreateDL(); } // destructor KX_Dome::~KX_Dome (void) { GLuint m_numimages = m_numfaces; ClearGLImages(); if(dlistSupported) glDeleteLists(dlistId, (GLsizei) m_numimages); } void KX_Dome::SetViewPort(GLuint viewport[4]) { if(canvaswidth != m_canvas->GetWidth() || canvasheight != m_canvas->GetHeight()) { m_viewport.SetLeft(viewport[0]); m_viewport.SetBottom(viewport[1]); m_viewport.SetRight(viewport[2]); m_viewport.SetTop(viewport[3]); CalculateImageSize(); } } void KX_Dome::CreateGLImages(void) { glGenTextures(m_numimages, (GLuint*)&domefacesId); for (int j=0;jGetWidth(); canvasheight = m_canvas->GetHeight(); m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth); m_buffersize *= m_resbuffer; //reduce buffer size for better performance int i = 0; while ((1 << i) <= m_buffersize) i++; m_imagesize = (1 << i); if (warp.usemesh){ warp.bufferwidth = canvaswidth; warp.bufferheight = canvasheight; i = 0; while ((1 << i) <= warp.bufferwidth) i++; warp.imagewidth = (1 << i); i = 0; while ((1 << i) <= warp.bufferheight) i++; warp.imageheight = (1 << i); } } bool KX_Dome::CreateDL(){ int i,j; dlistId = glGenLists((GLsizei) m_numimages); if (dlistId != 0) { if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED){ glNewList(dlistId, GL_COMPILE); GLDrawTriangles(cubetop, nfacestop); glEndList(); glNewList(dlistId+1, GL_COMPILE); GLDrawTriangles(cubebottom, nfacesbottom); glEndList(); glNewList(dlistId+2, GL_COMPILE); GLDrawTriangles(cubeleft, nfacesleft); glEndList(); glNewList(dlistId+3, GL_COMPILE); GLDrawTriangles(cuberight, nfacesright); glEndList(); if (m_angle > 180){ glNewList(dlistId+4, GL_COMPILE); GLDrawTriangles(cubefront, nfacesfront); glEndList(); } } else if (m_mode == DOME_PANORAM_SPH) { glNewList(dlistId, GL_COMPILE); GLDrawTriangles(cubetop, nfacestop); glEndList(); glNewList(dlistId+1, GL_COMPILE); GLDrawTriangles(cubebottom, nfacesbottom); glEndList(); glNewList(dlistId+2, GL_COMPILE); GLDrawTriangles(cubeleft, nfacesleft); glEndList(); glNewList(dlistId+3, GL_COMPILE); GLDrawTriangles(cuberight, nfacesright); glEndList(); glNewList(dlistId+4, GL_COMPILE); GLDrawTriangles(cubeleftback, nfacesleftback); glEndList(); glNewList(dlistId+5, GL_COMPILE); GLDrawTriangles(cuberightback, nfacesrightback); glEndList(); } if(warp.usemesh){ glNewList((dlistId + m_numfaces), GL_COMPILE); GLDrawWarpQuads(); glEndList(); } //clearing the vectors cubetop.clear(); cubebottom.clear(); cuberight.clear(); cubeleft.clear(); cubefront.clear(); cubeleftback.clear(); cuberightback.clear(); warp.nodes.clear(); } else // genList failed return false; return true; } void KX_Dome::GLDrawTriangles(vector & face, int nfaces) { int i,j; glBegin(GL_TRIANGLES); for (i=0;i columns, lines; lines = text.Explode('\n'); if(lines.size() < 6){ printf("Error: Warp Mesh File with insufficient data!\n"); return false; } columns = lines[1].Explode(' '); if(columns.size() !=2){ printf("Error: Warp Mesh File incorrect. The second line should contain: width height.\n"); return false; } warp.mode = atoi(lines[0]);// 1 = radial, 2 = fisheye warp.n_width = atoi(columns[0]); warp.n_height = atoi(columns[1]); if (lines.size() < 2 + (warp.n_width * warp.n_height)){ printf("Error: Warp Mesh File with insufficient data!\n"); return false; }else{ warp.nodes = vector > (warp.n_height, vector(warp.n_width)); for(i=2; i-2 < (warp.n_width*warp.n_height); i++){ columns = lines[i].Explode(' '); if (columns.size() == 5){ nodeX = (i-2)%warp.n_width; nodeY = ((i-2) - nodeX) / warp.n_width; warp.nodes[nodeY][nodeX].x = atof(columns[0]); warp.nodes[nodeY][nodeX].y = atof(columns[1]); warp.nodes[nodeY][nodeX].u = atof(columns[2]); warp.nodes[nodeY][nodeX].v = atof(columns[3]); warp.nodes[nodeY][nodeX].i = atof(columns[4]); } else{ warp.nodes.clear(); printf("Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n"); return false; } } } return true; } void KX_Dome::CreateMeshDome180(void) { /* 1)- Define the faces of half of a cube - each face is made out of 2 triangles 2) Subdivide the faces - more resolution == more curved lines 3) Spherize the cube - normalize the verts 4) Flatten onto xz plane - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image */ int i,j; float sqrt_2 = sqrt(2.0); float uv_ratio = (float)(m_buffersize-1) / m_imagesize; m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening //creating faces for the env mapcube 180º Dome // Top Face - just a triangle cubetop[0].verts[0][0] = -sqrt_2 / 2.0; cubetop[0].verts[0][1] = 0.0; cubetop[0].verts[0][2] = 0.5; cubetop[0].u[0] = 0.0; cubetop[0].v[0] = uv_ratio; cubetop[0].verts[1][0] = 0.0; cubetop[0].verts[1][1] = sqrt_2 / 2.0; cubetop[0].verts[1][2] = 0.5; cubetop[0].u[1] = 0.0; cubetop[0].v[1] = 0.0; cubetop[0].verts[2][0] = sqrt_2 / 2.0; cubetop[0].verts[2][1] = 0.0; cubetop[0].verts[2][2] = 0.5; cubetop[0].u[2] = uv_ratio; cubetop[0].v[2] = 0.0; nfacestop = 1; /* Bottom face - just a triangle */ cubebottom[0].verts[0][0] = -sqrt_2 / 2.0; cubebottom[0].verts[0][1] = 0.0; cubebottom[0].verts[0][2] = -0.5; cubebottom[0].u[0] = uv_ratio; cubebottom[0].v[0] = 0.0; cubebottom[0].verts[1][0] = sqrt_2 / 2.0; cubebottom[0].verts[1][1] = 0; cubebottom[0].verts[1][2] = -0.5; cubebottom[0].u[1] = 0.0; cubebottom[0].v[1] = uv_ratio; cubebottom[0].verts[2][0] = 0.0; cubebottom[0].verts[2][1] = sqrt_2 / 2.0; cubebottom[0].verts[2][2] = -0.5; cubebottom[0].u[2] = 0.0; cubebottom[0].v[2] = 0.0; nfacesbottom = 1; /* Left face - two triangles */ cubeleft[0].verts[0][0] = -sqrt_2 / 2.0; cubeleft[0].verts[0][1] = .0; cubeleft[0].verts[0][2] = -0.5; cubeleft[0].u[0] = 0.0; cubeleft[0].v[0] = 0.0; cubeleft[0].verts[1][0] = 0.0; cubeleft[0].verts[1][1] = sqrt_2 / 2.0; cubeleft[0].verts[1][2] = -0.5; cubeleft[0].u[1] = uv_ratio; cubeleft[0].v[1] = 0.0; cubeleft[0].verts[2][0] = -sqrt_2 / 2.0; cubeleft[0].verts[2][1] = 0.0; cubeleft[0].verts[2][2] = 0.5; cubeleft[0].u[2] = 0.0; cubeleft[0].v[2] = uv_ratio; //second triangle cubeleft[1].verts[0][0] = -sqrt_2 / 2.0; cubeleft[1].verts[0][1] = 0.0; cubeleft[1].verts[0][2] = 0.5; cubeleft[1].u[0] = 0.0; cubeleft[1].v[0] = uv_ratio; cubeleft[1].verts[1][0] = 0.0; cubeleft[1].verts[1][1] = sqrt_2 / 2.0; cubeleft[1].verts[1][2] = -0.5; cubeleft[1].u[1] = uv_ratio; cubeleft[1].v[1] = 0.0; cubeleft[1].verts[2][0] = 0.0; cubeleft[1].verts[2][1] = sqrt_2 / 2.0; cubeleft[1].verts[2][2] = 0.5; cubeleft[1].u[2] = uv_ratio; cubeleft[1].v[2] = uv_ratio; nfacesleft = 2; /* Right face - two triangles */ cuberight[0].verts[0][0] = 0.0; cuberight[0].verts[0][1] = sqrt_2 / 2.0; cuberight[0].verts[0][2] = -0.5; cuberight[0].u[0] = 0.0; cuberight[0].v[0] = 0.0; cuberight[0].verts[1][0] = sqrt_2 / 2.0; cuberight[0].verts[1][1] = 0.0; cuberight[0].verts[1][2] = -0.5; cuberight[0].u[1] = uv_ratio; cuberight[0].v[1] = 0.0; cuberight[0].verts[2][0] = sqrt_2 / 2.0; cuberight[0].verts[2][1] = 0.0; cuberight[0].verts[2][2] = 0.5; cuberight[0].u[2] = uv_ratio; cuberight[0].v[2] = uv_ratio; //second triangle cuberight[1].verts[0][0] = 0.0; cuberight[1].verts[0][1] = sqrt_2 / 2.0; cuberight[1].verts[0][2] = -0.5; cuberight[1].u[0] = 0.0; cuberight[1].v[0] = 0.0; cuberight[1].verts[1][0] = sqrt_2 / 2.0; cuberight[1].verts[1][1] = 0.0; cuberight[1].verts[1][2] = 0.5; cuberight[1].u[1] = uv_ratio; cuberight[1].v[1] = uv_ratio; cuberight[1].verts[2][0] = 0.0; cuberight[1].verts[2][1] = sqrt_2 / 2.0; cuberight[1].verts[2][2] = 0.5; cuberight[1].u[2] = 0.0; cuberight[1].v[2] = uv_ratio; nfacesright = 2; //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration //Could be made more efficient for drawing if the triangles were ordered in a fan. Not that important since we are using DisplayLists for(i=0;i 1.0){ //round the border verts[i][0] = cos(phi); verts[i][1] = -3.0; verts[i][2] = sin(phi); } } } void KX_Dome::FlattenPanorama(MT_Vector3 verts[3]) { // it creates a full spherical panoramic (360º) int i; double phi; bool edge=false; for (i=0;i<3;i++){ phi = atan2(verts[i][1], verts[i][0]); phi *= -1.0; //flipping if (phi == -MT_PI) //It's on the edge edge=true; verts[i][0] = phi / MT_PI; verts[i][1] = 0; verts[i][2] = atan2(verts[i][2], 1.0); verts[i][2] /= MT_PI / 2; } if(edge){ bool right=false; for (i=0;i<3;i++){ if(fmod(verts[i][0],1.0) > 0.0){ right=true; break; } } if(right){ for (i=0;i<3;i++){ if(verts[i][0] < 0.0) verts[i][0] *= -1.0; } } } } void KX_Dome::SplitFace(vector & face, int *nfaces) { int i; int n1, n2; n1 = n2 = *nfaces; for(i=0;iGetCameraNear(),cam->GetCameraFar()); */ RAS_FrameFrustum m_frustrum; //90 deg. Frustum m_frustrum.camnear = cam->GetCameraNear(); m_frustrum.camfar = cam->GetCameraFar(); // float top = tan(90.0*MT_PI/360.0) * m_frustrum.camnear; float top = m_frustrum.camnear; // for deg = 90º, tan = 1 m_frustrum.x1 = -top; m_frustrum.x2 = top; m_frustrum.y1 = -top; m_frustrum.y2 = top; m_projmat = m_rasterizer->GetFrustumMatrix( m_frustrum.x1, m_frustrum.x2, m_frustrum.y1, m_frustrum.y2, m_frustrum.camnear, m_frustrum.camfar); } void KX_Dome::CalculateCameraOrientation() { /* Uses 4 cameras for angles up to 180º Uses 5 cameras for angles up to 250º Uses 6 cameras for angles up to 360º */ float deg45 = MT_PI / 4; MT_Scalar c = cos(deg45); MT_Scalar s = sin(deg45); if ((m_mode == DOME_FISHEYE && m_angle <= 180)|| m_mode == DOME_TRUNCATED){ m_locRot[0] = MT_Matrix3x3( // 90º - Top c, -s, 0.0, 0.0,0.0, -1.0, s, c, 0.0); m_locRot[1] = MT_Matrix3x3( // 90º - Bottom -s, c, 0.0, 0.0,0.0, 1.0, s, c, 0.0); m_locRot[2] = MT_Matrix3x3( // 45º - Left c, 0.0, s, 0, 1.0, 0.0, -s, 0.0, c); m_locRot[3] = MT_Matrix3x3( // 45º - Right c, 0.0, -s, 0.0, 1.0, 0.0, s, 0.0, c); } else if ((m_mode == DOME_FISHEYE && m_angle > 180)){ m_locRot[0] = MT_Matrix3x3( // 90º - Top 1.0, 0.0, 0.0, 0.0, 0.0,-1.0, 0.0, 1.0, 0.0); m_locRot[1] = MT_Matrix3x3( // 90º - Bottom 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,-1.0, 0.0); m_locRot[2] = MT_Matrix3x3( // -90º - Left 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0); m_locRot[3] = MT_Matrix3x3( // 90º - Right 0.0, 0.0,-1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0); m_locRot[4] = MT_Matrix3x3( // 0º - Front 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); m_locRot[5] = MT_Matrix3x3( // 180º - Back - NOT USING -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,-1.0); } else if (m_mode == DOME_PANORAM_SPH){ m_locRot[0] = MT_Matrix3x3( // Top c, s, 0.0, 0.0,0.0, -1.0, -s, c, 0.0); m_locRot[1] = MT_Matrix3x3( // Bottom c, s, 0.0, 0.0 ,0.0, 1.0, s, -c, 0.0); m_locRot[2] = MT_Matrix3x3( // 45º - Left -s, 0.0, c, 0, 1.0, 0.0, -c, 0.0, -s); m_locRot[3] = MT_Matrix3x3( // 45º - Right c, 0.0, s, 0, 1.0, 0.0, -s, 0.0, c); m_locRot[4] = MT_Matrix3x3( // 135º - LeftBack -s, 0.0, -c, 0.0, 1.0, 0.0, c, 0.0, -s); m_locRot[5] = MT_Matrix3x3( // 135º - RightBack c, 0.0, -s, 0.0, 1.0, 0.0, s, 0.0, c); } } void KX_Dome::RotateCamera(KX_Camera* cam, int i) { // I'm not using it, I'm doing inline calls for these commands // but it's nice to have it here in case I need it MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation(); cam->NodeSetLocalOrientation(camori*m_locRot[i]); cam->NodeUpdateGS(0.f); MT_Transform camtrans(cam->GetWorldToCamera()); MT_Matrix4x4 viewmat(camtrans); m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(), cam->GetCameraLocation(), cam->GetCameraOrientation()); cam->SetModelviewMatrix(viewmat); // restore the original orientation cam->NodeSetLocalOrientation(camori); cam->NodeUpdateGS(0.f); } void KX_Dome::Draw(void) { switch(m_mode){ case DOME_FISHEYE: DrawDomeFisheye(); break; case DOME_TRUNCATED: DrawDomeFisheye(); break; case DOME_PANORAM_SPH: DrawPanorama(); break; } if(warp.usemesh) { glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight); DrawDomeWarped(); } } void KX_Dome::DrawDomeFisheye(void) { int i,j; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Making the viewport always square int can_width = m_viewport.GetRight(); int can_height = m_viewport.GetTop(); float ortho_width, ortho_height; if (warp.usemesh) glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost else if(m_mode == DOME_TRUNCATED){ ortho_width = 1.0; ortho_height = 2 * ((float)can_height/can_width) - 1.0 ; ortho_width /= m_size; ortho_height /= m_size; glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0); } else { if (can_width < can_height){ ortho_width = 1.0; ortho_height = (float)can_height/can_width; }else{ ortho_width = (float)can_width/can_height; ortho_height = 1.0; } ortho_width /= m_size; ortho_height /= m_size; glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); } glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0); if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) glPolygonMode(GL_FRONT, GL_LINE); else glPolygonMode(GL_FRONT, GL_FILL); glShadeModel(GL_SMOOTH); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glColor3f(1.0,1.0,1.0); if (dlistSupported){ for(i=0;i 180){ // front triangle glBindTexture(GL_TEXTURE_2D, domefacesId[4]); GLDrawTriangles(cubefront, nfacesfront); } } glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); } void KX_Dome::DrawPanorama(void) { int i,j; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Making the viewport always square int can_width = m_viewport.GetRight(); int can_height = m_viewport.GetTop(); float ortho_height = 1.0; float ortho_width = 1.0; if (warp.usemesh) glOrtho((-1.0), 1.0, (-0.5), 0.5, -20.0, 10.0); //stretch the image to reduce resolution lost else { //using all the screen if ((can_width / 2) <= (can_height)){ ortho_width = 1.0; ortho_height = (float)can_height/can_width; }else{ ortho_width = (float)can_width/can_height * 0.5; ortho_height = 0.5; } ortho_width /= m_size; ortho_height /= m_size; glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); } glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0); if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) glPolygonMode(GL_FRONT, GL_LINE); else glPolygonMode(GL_FRONT, GL_FILL); glShadeModel(GL_SMOOTH); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glColor3f(1.0,1.0,1.0); if (dlistSupported){ for(i=0;i (top) glBindTexture(GL_TEXTURE_2D, domefacesId[0]); GLDrawTriangles(cubetop, nfacestop); // domefacesId[5] => (bottom) glBindTexture(GL_TEXTURE_2D, domefacesId[1]); GLDrawTriangles(cubebottom, nfacesbottom); // domefacesId[1] => -45º (left) glBindTexture(GL_TEXTURE_2D, domefacesId[2]); GLDrawTriangles(cubeleft, nfacesleft); // domefacesId[2] => 45º (right) glBindTexture(GL_TEXTURE_2D, domefacesId[3]); GLDrawTriangles(cuberight, nfacesright); // domefacesId[0] => -135º (leftback) glBindTexture(GL_TEXTURE_2D, domefacesId[4]); GLDrawTriangles(cubeleftback, nfacesleftback); // domefacesId[3] => 135º (rightback) glBindTexture(GL_TEXTURE_2D, domefacesId[5]); GLDrawTriangles(cuberightback, nfacesrightback); } glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); } void KX_Dome::DrawDomeWarped(void) { int i,j; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Making the viewport always square int can_width = m_viewport.GetRight(); int can_height = m_viewport.GetTop(); double screen_ratio = can_width/ (double) can_height; screen_ratio /= m_size; glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 1.0, 0.0,0.0,0.0, 0.0,1.0,0.0); if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) glPolygonMode(GL_FRONT, GL_LINE); else glPolygonMode(GL_FRONT, GL_FILL); glShadeModel(GL_SMOOTH); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glColor3f(1.0,1.0,1.0); float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth; float uv_height = (float)(warp.bufferheight-1) / warp.imageheight; if (dlistSupported){ glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); glCallList(dlistId + m_numfaces); } else{ glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); GLDrawWarpQuads(); } glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); } void KX_Dome::BindImages(int i) { glBindTexture(GL_TEXTURE_2D, domefacesId[i]); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), m_buffersize, m_buffersize); } void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i) { if (!cam) return; m_canvas->SetViewPort(0,0,m_buffersize-1,m_buffersize-1); // m_rasterizer->SetAmbient(); m_rasterizer->DisplayFog(); CalculateFrustum(cam); //calculates m_projmat cam->SetProjectionMatrix(m_projmat); m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix()); // Dome_RotateCamera(cam,i); MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation(); cam->NodeSetLocalOrientation(camori*m_locRot[i]); cam->NodeUpdateGS(0.f); MT_Transform camtrans(cam->GetWorldToCamera()); MT_Matrix4x4 viewmat(camtrans); m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(), cam->GetCameraLocation(), cam->GetCameraOrientation()); cam->SetModelviewMatrix(viewmat); scene->CalculateVisibleMeshes(m_rasterizer,cam); scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); // restore the original orientation cam->NodeSetLocalOrientation(camori); cam->NodeUpdateGS(0.f); }