svn merge -r40197:40311 ^/trunk/blender
[blender.git] / source / gameengine / Ketsji / KX_Dome.cpp
1 /** \file gameengine/Ketsji/KX_Dome.cpp
2  *  \ingroup ketsji
3  */
4 /* $Id$
5 -----------------------------------------------------------------------------
6
7 This program is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the Free Software
9 Foundation; either version 2 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License along with
17 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
19 http://www.gnu.org/copyleft/lesser.txt.
20
21 Contributor(s): Dalai Felinto
22
23 This code is originally inspired on some of the ideas and codes from Paul Bourke.
24 Developed as part of a Research and Development project for SAT - La Société des arts technologiques.
25 -----------------------------------------------------------------------------
26 */
27
28 #include "KX_Dome.h"
29
30 #ifdef WITH_PYTHON
31 #include <structmember.h>
32 #endif
33
34 #include <float.h>
35 #include <math.h>
36
37 #include "DNA_scene_types.h"
38 #include "RAS_CameraData.h"
39 #include "BLI_math.h"
40
41 #include "GL/glew.h"
42
43 // constructor
44 KX_Dome::KX_Dome (
45         RAS_ICanvas* canvas,
46         /// rasterizer
47         RAS_IRasterizer* rasterizer,
48         /// render tools
49         RAS_IRenderTools* rendertools,
50         /// engine
51         KX_KetsjiEngine* engine,
52
53         short res,              //resolution of the mesh
54         short mode,             //mode - fisheye, truncated, warped, panoramic, ...
55         short angle,
56         float resbuf,   //size adjustment of the buffer
57         short tilt,
58         struct Text* warptext
59
60         ):
61     dlistSupported(false),
62     canvaswidth(-1), canvasheight(-1),
63     m_drawingmode(engine->GetDrawType()),
64     m_resolution(res),
65     m_mode(mode),
66     m_angle(angle),
67     m_resbuffer(resbuf),
68     m_tilt(tilt),
69     m_canvas(canvas),
70     m_rasterizer(rasterizer),
71     m_rendertools(rendertools),
72     m_engine(engine)
73 {
74         warp.usemesh = false;
75         fboSupported = false;
76
77         if (mode >= DOME_NUM_MODES)
78                 m_mode = DOME_FISHEYE;
79
80         if (warptext) // it there is a text data try to warp it
81         {
82                 char *buf;
83                 buf = txt_to_buf(warptext);
84                 if (buf)
85                 {
86                         warp.usemesh = ParseWarpMesh(STR_String(buf));
87                         MEM_freeN(buf);
88                 }
89         }
90
91         //setting the viewport size
92         GLuint  viewport[4]={0};
93         glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
94
95         SetViewPort(viewport);
96
97         switch(m_mode){
98                 case DOME_FISHEYE:
99                         if (m_angle <= 180){
100                                 cubetop.resize(1);
101                                 cubebottom.resize(1);
102                                 cubeleft.resize(2);
103                                 cuberight.resize(2);
104
105                                 CreateMeshDome180();
106                                 m_numfaces = 4;
107                         }else if (m_angle > 180){
108                                 cubetop.resize(2);
109                                 cubebottom.resize(2);
110                                 cubeleft.resize(2);
111                                 cubefront.resize(2);
112                                 cuberight.resize(2);
113
114                                 CreateMeshDome250();
115                                 m_numfaces = 5;
116                         } break;
117                 case DOME_ENVMAP:
118                         m_angle = 360;
119                         m_numfaces = 6;
120                         break;
121                 case DOME_PANORAM_SPH:
122                         cubeleft.resize(2);
123                         cubeleftback.resize(2);
124                         cuberight.resize(2);
125                         cuberightback.resize(2);
126                         cubetop.resize(2);
127                         cubebottom.resize(2);
128
129                         m_angle = 360;
130                         CreateMeshPanorama();
131                         m_numfaces = 6;
132                         break;
133                 default: //DOME_TRUNCATED_FRONT and DOME_TRUNCATED_REAR
134                         if (m_angle <= 180){
135                                 cubetop.resize(1);
136                                 cubebottom.resize(1);
137                                 cubeleft.resize(2);
138                                 cuberight.resize(2);
139
140                                 CreateMeshDome180();
141                                 m_numfaces = 4;
142                         }else if (m_angle > 180){
143                                 cubetop.resize(2);
144                                 cubebottom.resize(2);
145                                 cubeleft.resize(2);
146                                 cubefront.resize(2);
147                                 cuberight.resize(2);
148
149                                 CreateMeshDome250();
150                                 m_numfaces = 5;
151                         } break;
152         }
153
154         m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces);
155
156         CalculateCameraOrientation();
157
158         CreateGLImages();
159
160         if(warp.usemesh)
161                 fboSupported = CreateFBO();
162
163         dlistSupported = CreateDL();
164 }
165
166 // destructor
167 KX_Dome::~KX_Dome (void)
168 {
169         ClearGLImages();
170
171         if(fboSupported)
172                 glDeleteFramebuffersEXT(1, &warp.fboId);
173
174         if(dlistSupported)
175                 glDeleteLists(dlistId, (GLsizei) m_numimages);
176 }
177
178 void KX_Dome::SetViewPort(GLuint viewport[4])
179 {
180         if(canvaswidth != m_viewport.GetWidth() || canvasheight != m_viewport.GetHeight())
181         {
182                 m_viewport.SetLeft(viewport[0]); 
183                 m_viewport.SetBottom(viewport[1]);
184                 m_viewport.SetRight(viewport[2]);
185                 m_viewport.SetTop(viewport[3]);
186
187                 CalculateImageSize();
188         }
189 }
190
191 void KX_Dome::CreateGLImages(void)
192 {
193         glGenTextures(m_numimages, (GLuint*)&domefacesId);
194
195         for (int j=0;j<m_numfaces;j++){
196                 glBindTexture(GL_TEXTURE_2D, domefacesId[j]);
197                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_imagesize, m_imagesize, 0, GL_RGB8,
198                                 GL_UNSIGNED_BYTE, 0);
199                 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, m_imagesize, m_imagesize, 0);
200                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
201                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
202                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
203                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
204         }
205         if(warp.usemesh){
206                 glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
207                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagesize, warp.imagesize, 0, GL_RGB8,
208                                 GL_UNSIGNED_BYTE, 0);
209                 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagesize, warp.imagesize, 0);
210                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
211                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
212                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
213                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
214         }
215 }
216
217 void KX_Dome::ClearGLImages(void)
218 {
219         glDeleteTextures(m_numimages, (GLuint*)&domefacesId);
220 /*
221         for (int i=0;i<m_numimages;i++)
222                 if(glIsTexture(domefacesId[i]))
223                         glDeleteTextures(1, (GLuint*)&domefacesId[i]);
224 */
225 }
226
227 void KX_Dome::CalculateImageSize(void)
228 {
229 /*
230 - determine the minimum buffer size
231 - reduce the buffer for better performace
232 - create a power of 2 texture bigger than the buffer
233 */
234 /*
235 Blender handles Canvas size differently when in fullscreen mode.
236 We are manually checking for that. Although it's a hack, it works.
237
238 Bug reported here: #18655 - Inconsistency of pixels in canvas dimensions when in maximized mode (affecting BGE Dome)
239 http://projects.blender.org/tracker/?func=detail&aid=18655&group_id=9&atid=125
240 */
241
242         canvaswidth = m_canvas->GetWidth();
243         canvasheight = m_canvas->GetHeight();
244
245         bool fullscreen(false); //XXX HACK
246         fullscreen = (canvaswidth != m_viewport.GetWidth());
247
248         m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth);
249         m_buffersize = (int)(m_buffersize*m_resbuffer); //reduce buffer size for better performance
250         
251         if (fullscreen) //XXX HACK
252                 m_buffersize --;
253
254         int i = 0;
255         while ((1 << i) <= m_buffersize)
256                 i++;
257         m_imagesize = (1 << i);
258
259         if (warp.usemesh){
260                 // warp FBO needs to be up to twice as big as m_buffersize to get more resolution
261                 warp.imagesize = m_imagesize;
262                 if (m_buffersize == m_imagesize)
263                         warp.imagesize *= 2;
264
265                 //if FBO is not working/supported, we use the canvas dimension as buffer
266                 warp.bufferwidth  = canvaswidth;
267                 warp.bufferheight = canvasheight;
268         }
269
270         //XXX HACK
271         canvaswidth  = m_viewport.GetWidth();
272         canvasheight = m_viewport.GetHeight();
273 }
274
275 bool KX_Dome::CreateDL(){
276         dlistId = glGenLists((GLsizei) m_numimages);
277         if (dlistId != 0) {
278                 if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED_FRONT || m_mode == DOME_TRUNCATED_REAR){
279                         glNewList(dlistId, GL_COMPILE);
280                                 GLDrawTriangles(cubetop, nfacestop);
281                         glEndList();
282
283                         glNewList(dlistId+1, GL_COMPILE);
284                                 GLDrawTriangles(cubebottom, nfacesbottom);
285                         glEndList();
286
287                         glNewList(dlistId+2, GL_COMPILE);
288                                 GLDrawTriangles(cubeleft, nfacesleft);
289                         glEndList();
290
291                         glNewList(dlistId+3, GL_COMPILE);
292                                 GLDrawTriangles(cuberight, nfacesright);
293                         glEndList();
294
295                         if (m_angle > 180){
296                                 glNewList(dlistId+4, GL_COMPILE);
297                                         GLDrawTriangles(cubefront, nfacesfront);
298                                 glEndList();
299                         }
300                 }
301                 else if (m_mode == DOME_PANORAM_SPH)
302                 {
303                         glNewList(dlistId, GL_COMPILE);
304                                 GLDrawTriangles(cubetop, nfacestop);
305                         glEndList();
306
307                         glNewList(dlistId+1, GL_COMPILE);
308                                 GLDrawTriangles(cubebottom, nfacesbottom);
309                         glEndList();
310
311                         glNewList(dlistId+2, GL_COMPILE);
312                                 GLDrawTriangles(cubeleft, nfacesleft);
313                         glEndList();
314
315                         glNewList(dlistId+3, GL_COMPILE);
316                                 GLDrawTriangles(cuberight, nfacesright);
317                         glEndList();
318
319                         glNewList(dlistId+4, GL_COMPILE);
320                                 GLDrawTriangles(cubeleftback, nfacesleftback);
321                         glEndList();
322
323                         glNewList(dlistId+5, GL_COMPILE);
324                                 GLDrawTriangles(cuberightback, nfacesrightback);
325                         glEndList();
326                 }
327
328                 if(warp.usemesh){
329                         glNewList((dlistId + m_numfaces), GL_COMPILE);
330                                 GLDrawWarpQuads();
331                         glEndList();
332                 }
333
334                 //clearing the vectors 
335                 cubetop.clear();
336                 cubebottom.clear();
337                 cuberight.clear();
338                 cubeleft.clear();
339                 cubefront.clear();
340                 cubeleftback.clear();
341                 cuberightback.clear();
342                 warp.nodes.clear();
343
344         } else // genList failed
345                 return false;
346
347         return true;
348 }
349
350 bool KX_Dome::CreateFBO(void)
351 {
352         if (!GLEW_EXT_framebuffer_object)
353         {
354                 printf("Dome Error: FrameBuffer unsupported. Using low resolution warp image.");
355                 return false;
356         }
357
358         glGenFramebuffersEXT(1, &warp.fboId);
359         if(warp.fboId==0)
360         {
361                 printf("Dome Error: Invalid frame buffer object. Using low resolution warp image.");
362                 return false;
363         }
364
365         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
366
367         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
368                 GL_TEXTURE_2D, domefacesId[m_numfaces], 0);
369
370         GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
371
372         if(status == GL_FRAMEBUFFER_UNSUPPORTED_EXT)
373         {
374                 printf("Dome Error: FrameBuffer settings unsupported. Using low resolution warp image.");
375                 return false;
376         }
377         else if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
378         {
379                 glDeleteFramebuffersEXT(1, &warp.fboId);
380                 return false;
381         }
382
383         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
384
385         //nothing failed: we can use the whole FBO as buffersize
386         warp.bufferwidth = warp.bufferheight = warp.imagesize;
387         return true;
388 }
389
390 void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces)
391 {
392         int i,j;
393         glBegin(GL_TRIANGLES);
394                 for (i=0;i<nfaces;i++) {
395                         for (j=0;j<3;j++) {
396                                 glTexCoord2f(face[i].u[j],face[i].v[j]);
397                                 glVertex3f((GLfloat)face[i].verts[j][0],(GLfloat)face[i].verts[j][1],(GLfloat)face[i].verts[j][2]);
398                         }
399                 }
400         glEnd();
401 }
402
403 void KX_Dome::GLDrawWarpQuads(void)
404 {
405         int i, j, i2;
406
407         float uv_width = (float)(warp.bufferwidth) / warp.imagesize;
408         float uv_height = (float)(warp.bufferheight) / warp.imagesize;
409
410         if(warp.mode ==2 ){
411                 glBegin(GL_QUADS);
412                 for (i=0;i<warp.n_height-1;i++) {
413                         for (j=0;j<warp.n_width-1;j++) {
414                                 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)
415                                         continue;
416
417                                 glColor3f(warp.nodes[i][j].i, warp.nodes[i][j].i, warp.nodes[i][j].i);
418                                 glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height));
419                                 glVertex3f(warp.nodes[i][j].x, warp.nodes[i][j].y,0.0);
420
421                                 glColor3f(warp.nodes[i+1][j].i, warp.nodes[i+1][j].i, warp.nodes[i+1][j].i);
422                                 glTexCoord2f((warp.nodes[i+1][j].u * uv_width), (warp.nodes[i+1][j].v * uv_height));
423                                 glVertex3f(warp.nodes[i+1][j].x, warp.nodes[i+1][j].y,0.0);
424
425                                 glColor3f(warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i);
426                                 glTexCoord2f((warp.nodes[i+1][j+1].u * uv_width), (warp.nodes[i+1][j+1].v * uv_height));
427                                 glVertex3f(warp.nodes[i+1][j+1].x, warp.nodes[i+1][j+1].y,0.0);
428
429                                 glColor3f(warp.nodes[i][j+1].i, warp.nodes[i][j+1].i, warp.nodes[i][j+1].i);
430                                 glTexCoord2f((warp.nodes[i][j+1].u * uv_width), (warp.nodes[i][j+1].v * uv_height));
431                                 glVertex3f(warp.nodes[i][j+1].x, warp.nodes[i][j+1].y,0.0);
432                         }
433                 }
434                 glEnd();
435         }
436         else if (warp.mode == 1){
437                 glBegin(GL_QUADS);
438                 for (i=0;i<warp.n_height-1;i++) {
439                         for (j=0;j<warp.n_width-1;j++) {
440                                 i2 = (i+1) % warp.n_width; // Wrap around, i = warp.n_width = 0
441
442                                 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)
443                                         continue;
444
445                                  glColor3f(warp.nodes[i][j].i,warp.nodes[i][j].i,warp.nodes[i][j].i);
446                                  glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height));
447                                  glVertex3f(warp.nodes[i][j].x,warp.nodes[i][j].y,0.0);
448
449                                  glColor3f(warp.nodes[i2][j].i,warp.nodes[i2][j].i,warp.nodes[i2][j].i);
450                                  glTexCoord2f((warp.nodes[i2][j].u * uv_width), (warp.nodes[i2][j].v * uv_height));
451                                  glVertex3f(warp.nodes[i2][j].x,warp.nodes[i2][j].y,0.0);
452
453                                  glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i);
454                                  glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height));
455                                  glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0);
456
457                                  glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i);
458                                  glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height));
459                                  glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0);
460
461                         }
462                 }
463                 glEnd();
464         } else{
465                 printf("Dome Error: Warp Mode %d unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n", warp.mode);
466         }
467 }
468
469
470 bool KX_Dome::ParseWarpMesh(STR_String text)
471 {
472 /*
473 //Notes about the supported data format:
474 File example::
475         mode
476         width height
477         n0_x n0_y n0_u n0_v n0_i
478         n1_x n1_y n1_u n1_v n1_i
479         n2_x n1_y n2_u n2_v n2_i
480         n3_x n3_y n3_u n3_v n3_i
481         (...)
482 First line is the image type the mesh is support to be applied to: 2 = fisheye, 1=radial
483 Tthe next line has the mesh dimensions
484 Rest of the lines are the nodes of the mesh. Each line has x y u v i
485   (x,y) are the normalised screen coordinates
486   (u,v) texture coordinates
487   i a multiplicative intensity factor
488
489 x varies from -screen aspect to screen aspect
490 y varies from -1 to 1
491 u and v vary from 0 to 1
492 i ranges from 0 to 1, if negative don't draw that mesh node
493 */
494         int i;
495         int nodeX=0, nodeY=0;
496
497         vector<STR_String> columns, lines;
498
499         lines = text.Explode('\n');
500         if(lines.size() < 6){
501                 printf("Dome Error: Warp Mesh File with insufficient data!\n");
502                 return false;
503         }
504         columns = lines[1].Explode(' ');
505         if(columns.size() == 1)
506                 columns = lines[1].Explode('\t');
507
508         if(columns.size() !=2){
509                 printf("Dome Error: Warp Mesh File incorrect. The second line should contain: width height.\n");
510                 return false;
511         }
512
513         warp.mode = atoi(lines[0]);// 1 = radial, 2 = fisheye
514
515         warp.n_width = atoi(columns[0]);
516         warp.n_height = atoi(columns[1]);
517
518         if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)){
519                 printf("Dome Error: Warp Mesh File with insufficient data!\n");
520                 return false;
521         }else{
522                 warp.nodes = vector<vector<WarpMeshNode> > (warp.n_height, vector<WarpMeshNode>(warp.n_width));
523
524                 for(i=2; i-2 < (warp.n_width*warp.n_height); i++){
525                         columns = lines[i].Explode(' ');
526                         if(columns.size() == 1)
527                                 columns = lines[i].Explode('\t');
528
529                         if (columns.size() == 5){
530                                 nodeX = (i-2)%warp.n_width;
531                                 nodeY = ((i-2) - nodeX) / warp.n_width;
532
533                                 warp.nodes[nodeY][nodeX].x = atof(columns[0]);
534                                 warp.nodes[nodeY][nodeX].y = atof(columns[1]);
535                                 warp.nodes[nodeY][nodeX].u = atof(columns[2]);
536                                 warp.nodes[nodeY][nodeX].v = atof(columns[3]);
537                                 warp.nodes[nodeY][nodeX].i = atof(columns[4]);
538                         }
539                         else{
540                                 warp.nodes.clear();
541                                 printf("Dome Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n");
542                                 return false;
543                         }
544                 }
545         }
546         return true;
547 }
548
549 void KX_Dome::CreateMeshDome180(void)
550 {
551 /*
552 1)-  Define the faces of half of a cube 
553  - each face is made out of 2 triangles
554 2) Subdivide the faces
555  - more resolution == more curved lines
556 3) Spherize the cube
557  - normalize the verts
558 4) Flatten onto xz plane
559  - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image
560 */
561         int i,j;
562         float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
563
564         m_radangle = DEG2RADF(m_angle); //calculates the radians angle, used for flattening
565
566         //creating faces for the env mapcube 180deg Dome
567         // Top Face - just a triangle
568         cubetop[0].verts[0][0] = -M_SQRT2 / 2.0;
569         cubetop[0].verts[0][1] = 0.0;
570         cubetop[0].verts[0][2] = 0.5;
571         cubetop[0].u[0] = 0.0;
572         cubetop[0].v[0] = uv_ratio;
573
574         cubetop[0].verts[1][0] = 0.0;
575         cubetop[0].verts[1][1] = M_SQRT2 / 2.0;
576         cubetop[0].verts[1][2] = 0.5;
577         cubetop[0].u[1] = 0.0;
578         cubetop[0].v[1] = 0.0;
579
580         cubetop[0].verts[2][0] = M_SQRT2 / 2.0;
581         cubetop[0].verts[2][1] = 0.0;
582         cubetop[0].verts[2][2] = 0.5;
583         cubetop[0].u[2] = uv_ratio;
584         cubetop[0].v[2] = 0.0;
585
586         nfacestop = 1;
587
588         /* Bottom face - just a triangle */
589         cubebottom[0].verts[0][0] = -M_SQRT2 / 2.0;
590         cubebottom[0].verts[0][1] = 0.0;
591         cubebottom[0].verts[0][2] = -0.5;
592         cubebottom[0].u[0] = uv_ratio;
593         cubebottom[0].v[0] = 0.0;
594
595         cubebottom[0].verts[1][0] = M_SQRT2 / 2.0;
596         cubebottom[0].verts[1][1] = 0;
597         cubebottom[0].verts[1][2] = -0.5;
598         cubebottom[0].u[1] = 0.0;
599         cubebottom[0].v[1] = uv_ratio;
600
601         cubebottom[0].verts[2][0] = 0.0;
602         cubebottom[0].verts[2][1] = M_SQRT2 / 2.0;
603         cubebottom[0].verts[2][2] = -0.5;
604         cubebottom[0].u[2] = 0.0;
605         cubebottom[0].v[2] = 0.0;
606
607         nfacesbottom = 1;       
608         
609         /* Left face - two triangles */
610         
611         cubeleft[0].verts[0][0] = -M_SQRT2 / 2.0;
612         cubeleft[0].verts[0][1] = .0;
613         cubeleft[0].verts[0][2] = -0.5;
614         cubeleft[0].u[0] = 0.0;
615         cubeleft[0].v[0] = 0.0;
616
617         cubeleft[0].verts[1][0] = 0.0;
618         cubeleft[0].verts[1][1] = M_SQRT2 / 2.0;
619         cubeleft[0].verts[1][2] = -0.5;
620         cubeleft[0].u[1] = uv_ratio;
621         cubeleft[0].v[1] = 0.0;
622
623         cubeleft[0].verts[2][0] = -M_SQRT2 / 2.0;
624         cubeleft[0].verts[2][1] = 0.0;
625         cubeleft[0].verts[2][2] = 0.5;
626         cubeleft[0].u[2] = 0.0;
627         cubeleft[0].v[2] = uv_ratio;
628
629         //second triangle
630         cubeleft[1].verts[0][0] = -M_SQRT2 / 2.0;
631         cubeleft[1].verts[0][1] = 0.0;
632         cubeleft[1].verts[0][2] = 0.5;
633         cubeleft[1].u[0] = 0.0;
634         cubeleft[1].v[0] = uv_ratio;
635
636         cubeleft[1].verts[1][0] = 0.0;
637         cubeleft[1].verts[1][1] = M_SQRT2 / 2.0;
638         cubeleft[1].verts[1][2] = -0.5;
639         cubeleft[1].u[1] = uv_ratio;
640         cubeleft[1].v[1] = 0.0;
641
642         cubeleft[1].verts[2][0] = 0.0;
643         cubeleft[1].verts[2][1] = M_SQRT2 / 2.0;
644         cubeleft[1].verts[2][2] = 0.5;
645         cubeleft[1].u[2] = uv_ratio;
646         cubeleft[1].v[2] = uv_ratio;
647
648         nfacesleft = 2;
649         
650         /* Right face - two triangles */
651         cuberight[0].verts[0][0] = 0.0;
652         cuberight[0].verts[0][1] = M_SQRT2 / 2.0;
653         cuberight[0].verts[0][2] = -0.5;
654         cuberight[0].u[0] = 0.0;
655         cuberight[0].v[0] = 0.0;
656
657         cuberight[0].verts[1][0] = M_SQRT2 / 2.0;
658         cuberight[0].verts[1][1] = 0.0;
659         cuberight[0].verts[1][2] = -0.5;
660         cuberight[0].u[1] = uv_ratio;
661         cuberight[0].v[1] = 0.0;
662
663         cuberight[0].verts[2][0] = M_SQRT2 / 2.0;
664         cuberight[0].verts[2][1] = 0.0;
665         cuberight[0].verts[2][2] = 0.5;
666         cuberight[0].u[2] = uv_ratio;
667         cuberight[0].v[2] = uv_ratio;
668
669         //second triangle
670         cuberight[1].verts[0][0] = 0.0;
671         cuberight[1].verts[0][1] = M_SQRT2 / 2.0;
672         cuberight[1].verts[0][2] = -0.5;
673         cuberight[1].u[0] = 0.0;
674         cuberight[1].v[0] = 0.0;
675
676         cuberight[1].verts[1][0] = M_SQRT2 / 2.0;
677         cuberight[1].verts[1][1] = 0.0;
678         cuberight[1].verts[1][2] = 0.5;
679         cuberight[1].u[1] = uv_ratio;
680         cuberight[1].v[1] = uv_ratio;
681
682         cuberight[1].verts[2][0] = 0.0;
683         cuberight[1].verts[2][1] = M_SQRT2 / 2.0;
684         cuberight[1].verts[2][2] = 0.5;
685         cuberight[1].u[2] = 0.0;
686         cuberight[1].v[2] = uv_ratio;
687
688         nfacesright = 2;
689         
690         //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration
691         //Could be made more efficient for drawing if the triangles were ordered in a fan. Not that important since we are using DisplayLists
692
693         for(i=0;i<m_resolution;i++){
694                 cubetop.resize(4*nfacestop);
695                 SplitFace(cubetop,&nfacestop);
696                 cubebottom.resize(4*nfacesbottom);
697                 SplitFace(cubebottom,&nfacesbottom);    
698                 cubeleft.resize(4*nfacesleft);
699                 SplitFace(cubeleft,&nfacesleft);
700                 cuberight.resize(4*nfacesright);
701                 SplitFace(cuberight,&nfacesright);
702         }               
703
704         // Turn into a hemisphere
705         for(j=0;j<3;j++){
706                 for(i=0;i<nfacestop;i++)
707                         cubetop[i].verts[j].normalize();
708                 for(i=0;i<nfacesbottom;i++)
709                         cubebottom[i].verts[j].normalize();
710                 for(i=0;i<nfacesleft;i++)
711                         cubeleft[i].verts[j].normalize();
712                 for(i=0;i<nfacesright;i++)
713                         cuberight[i].verts[j].normalize();
714         }
715
716         //flatten onto xz plane
717         for(i=0;i<nfacestop;i++)
718                 FlattenDome(cubetop[i].verts);
719         for(i=0;i<nfacesbottom;i++)
720                 FlattenDome(cubebottom[i].verts);
721         for(i=0;i<nfacesleft;i++)
722                 FlattenDome(cubeleft[i].verts);
723         for(i=0;i<nfacesright;i++)
724                 FlattenDome(cuberight[i].verts);
725
726 }
727
728 void KX_Dome::CreateMeshDome250(void)
729 {
730 /*
731 1)-  Define the faces of a cube without the back face
732  - each face is made out of 2 triangles
733 2) Subdivide the faces
734  - more resolution == more curved lines
735 3) Spherize the cube
736  - normalize the verts
737 4) Flatten onto xz plane
738  - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image
739 */
740
741         int i,j;
742         float uv_height, uv_base;
743         float verts_height;
744
745         float rad_ang = m_angle * MT_PI / 180.0;
746         float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
747
748         m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening
749 /*
750 verts_height is the exactly needed height of the cube faces (not always 1.0).
751 When we want some horizontal information (e.g. for horizontal 220deg domes) we don't need to create and tesselate the whole cube.
752 Therefore the lateral cube faces could be small, and the tesselate mesh would be completely used.
753 (if we always worked with verts_height = 1.0, we would be discarding a lot of the calculated and tesselated geometry).
754
755 So I came out with this formula:
756 verts_height = tan((rad_ang/2) - (MT_PI/2))*sqrt(2.0);
757
758 Here we take half the sphere(rad_ang/2) and subtract a quarter of it (MT_PI/2)
759 Therefore we have the length in radians of the dome/sphere over the horizon.
760 Once we take the tangent of that angle, you have the verts coordinate corresponding to the verts on the side faces.
761 Then we need to multiply it by sqrt(2.0) to get the coordinate of the verts on the diagonal of the original cube.
762 */
763         verts_height = tan((rad_ang/2) - (MT_PI/2))*M_SQRT2;
764
765         uv_height = uv_ratio * ((verts_height/2) + 0.5);
766         uv_base = uv_ratio * (1.0 - ((verts_height/2) + 0.5));
767         
768         //creating faces for the env mapcube 180deg Dome
769         // Front Face - 2 triangles
770         cubefront[0].verts[0][0] =-1.0;
771         cubefront[0].verts[0][1] = 1.0;
772         cubefront[0].verts[0][2] =-1.0;
773         cubefront[0].u[0] = 0.0;
774         cubefront[0].v[0] = 0.0;
775
776         cubefront[0].verts[1][0] = 1.0;
777         cubefront[0].verts[1][1] = 1.0;
778         cubefront[0].verts[1][2] = 1.0; 
779         cubefront[0].u[1] = uv_ratio;
780         cubefront[0].v[1] = uv_ratio;
781
782         cubefront[0].verts[2][0] =-1.0;
783         cubefront[0].verts[2][1] = 1.0;
784         cubefront[0].verts[2][2] = 1.0; 
785         cubefront[0].u[2] = 0.0;
786         cubefront[0].v[2] = uv_ratio;
787
788         //second triangle
789         cubefront[1].verts[0][0] = 1.0;
790         cubefront[1].verts[0][1] = 1.0;
791         cubefront[1].verts[0][2] = 1.0;
792         cubefront[1].u[0] = uv_ratio;
793         cubefront[1].v[0] = uv_ratio;
794
795         cubefront[1].verts[1][0] =-1.0;
796         cubefront[1].verts[1][1] = 1.0;
797         cubefront[1].verts[1][2] =-1.0; 
798         cubefront[1].u[1] = 0.0;
799         cubefront[1].v[1] = 0.0;
800
801         cubefront[1].verts[2][0] = 1.0;
802         cubefront[1].verts[2][1] = 1.0;
803         cubefront[1].verts[2][2] =-1.0; 
804         cubefront[1].u[2] = uv_ratio;
805         cubefront[1].v[2] = 0.0;
806
807         nfacesfront = 2;
808
809         // Left Face - 2 triangles
810         cubeleft[0].verts[0][0] =-1.0;
811         cubeleft[0].verts[0][1] = 1.0;
812         cubeleft[0].verts[0][2] =-1.0;
813         cubeleft[0].u[0] = uv_ratio;
814         cubeleft[0].v[0] = 0.0;
815
816         cubeleft[0].verts[1][0] =-1.0;
817         cubeleft[0].verts[1][1] =-verts_height;
818         cubeleft[0].verts[1][2] = 1.0;  
819         cubeleft[0].u[1] = uv_base;
820         cubeleft[0].v[1] = uv_ratio;
821
822         cubeleft[0].verts[2][0] =-1.0;
823         cubeleft[0].verts[2][1] =-verts_height;
824         cubeleft[0].verts[2][2] =-1.0;  
825         cubeleft[0].u[2] = uv_base;
826         cubeleft[0].v[2] = 0.0;
827
828         //second triangle
829         cubeleft[1].verts[0][0] =-1.0;
830         cubeleft[1].verts[0][1] =-verts_height;
831         cubeleft[1].verts[0][2] = 1.0;
832         cubeleft[1].u[0] = uv_base;
833         cubeleft[1].v[0] = uv_ratio;
834
835         cubeleft[1].verts[1][0] =-1.0;
836         cubeleft[1].verts[1][1] = 1.0;
837         cubeleft[1].verts[1][2] =-1.0;  
838         cubeleft[1].u[1] = uv_ratio;
839         cubeleft[1].v[1] = 0.0;
840
841         cubeleft[1].verts[2][0] =-1.0;
842         cubeleft[1].verts[2][1] = 1.0;
843         cubeleft[1].verts[2][2] = 1.0;  
844         cubeleft[1].u[2] = uv_ratio;
845         cubeleft[1].v[2] = uv_ratio;
846
847         nfacesleft = 2;
848
849         // right Face - 2 triangles
850         cuberight[0].verts[0][0] = 1.0;
851         cuberight[0].verts[0][1] = 1.0;
852         cuberight[0].verts[0][2] = 1.0;
853         cuberight[0].u[0] = 0.0;
854         cuberight[0].v[0] = uv_ratio;
855
856         cuberight[0].verts[1][0] = 1.0;
857         cuberight[0].verts[1][1] =-verts_height;
858         cuberight[0].verts[1][2] =-1.0; 
859         cuberight[0].u[1] = uv_height;
860         cuberight[0].v[1] = 0.0;
861
862         cuberight[0].verts[2][0] = 1.0;
863         cuberight[0].verts[2][1] =-verts_height;
864         cuberight[0].verts[2][2] = 1.0; 
865         cuberight[0].u[2] = uv_height;
866         cuberight[0].v[2] = uv_ratio;
867
868         //second triangle
869         cuberight[1].verts[0][0] = 1.0;
870         cuberight[1].verts[0][1] =-verts_height;
871         cuberight[1].verts[0][2] =-1.0;
872         cuberight[1].u[0] = uv_height;
873         cuberight[1].v[0] = 0.0;
874
875         cuberight[1].verts[1][0] = 1.0;
876         cuberight[1].verts[1][1] = 1.0;
877         cuberight[1].verts[1][2] = 1.0; 
878         cuberight[1].u[1] = 0.0;
879         cuberight[1].v[1] = uv_ratio;
880
881         cuberight[1].verts[2][0] = 1.0;
882         cuberight[1].verts[2][1] = 1.0;
883         cuberight[1].verts[2][2] =-1.0; 
884         cuberight[1].u[2] = 0.0;
885         cuberight[1].v[2] = 0.0;
886
887         nfacesright = 2;
888
889         // top Face - 2 triangles
890         cubetop[0].verts[0][0] =-1.0;
891         cubetop[0].verts[0][1] = 1.0;
892         cubetop[0].verts[0][2] = 1.0;
893         cubetop[0].u[0] = 0.0;
894         cubetop[0].v[0] = 0.0;
895
896         cubetop[0].verts[1][0] = 1.0;
897         cubetop[0].verts[1][1] =-verts_height;
898         cubetop[0].verts[1][2] = 1.0;   
899         cubetop[0].u[1] = uv_ratio;
900         cubetop[0].v[1] = uv_height;
901
902         cubetop[0].verts[2][0] =-1.0;
903         cubetop[0].verts[2][1] =-verts_height;
904         cubetop[0].verts[2][2] = 1.0;   
905         cubetop[0].u[2] = 0.0;
906         cubetop[0].v[2] = uv_height;
907
908         //second triangle
909         cubetop[1].verts[0][0] = 1.0;
910         cubetop[1].verts[0][1] =-verts_height;
911         cubetop[1].verts[0][2] = 1.0;
912         cubetop[1].u[0] = uv_ratio;
913         cubetop[1].v[0] = uv_height;
914
915         cubetop[1].verts[1][0] =-1.0;
916         cubetop[1].verts[1][1] = 1.0;
917         cubetop[1].verts[1][2] = 1.0;   
918         cubetop[1].u[1] = 0.0;
919         cubetop[1].v[1] = 0.0;
920
921         cubetop[1].verts[2][0] = 1.0;
922         cubetop[1].verts[2][1] = 1.0;
923         cubetop[1].verts[2][2] = 1.0;   
924         cubetop[1].u[2] = uv_ratio;
925         cubetop[1].v[2] = 0.0;
926
927         nfacestop = 2;
928
929         // bottom Face - 2 triangles
930         cubebottom[0].verts[0][0] =-1.0;
931         cubebottom[0].verts[0][1] =-verts_height;
932         cubebottom[0].verts[0][2] =-1.0;
933         cubebottom[0].u[0] = 0.0;
934         cubebottom[0].v[0] = uv_base;
935
936         cubebottom[0].verts[1][0] = 1.0;
937         cubebottom[0].verts[1][1] = 1.0;
938         cubebottom[0].verts[1][2] =-1.0;        
939         cubebottom[0].u[1] = uv_ratio;
940         cubebottom[0].v[1] = uv_ratio;
941
942         cubebottom[0].verts[2][0] =-1.0;
943         cubebottom[0].verts[2][1] = 1.0;
944         cubebottom[0].verts[2][2] =-1.0;        
945         cubebottom[0].u[2] = 0.0;
946         cubebottom[0].v[2] = uv_ratio;
947
948         //second triangle
949         cubebottom[1].verts[0][0] = 1.0;
950         cubebottom[1].verts[0][1] = 1.0;
951         cubebottom[1].verts[0][2] =-1.0;
952         cubebottom[1].u[0] = uv_ratio;
953         cubebottom[1].v[0] = uv_ratio;
954
955         cubebottom[1].verts[1][0] =-1.0;
956         cubebottom[1].verts[1][1] =-verts_height;
957         cubebottom[1].verts[1][2] =-1.0;        
958         cubebottom[1].u[1] = 0.0;
959         cubebottom[1].v[1] = uv_base;
960
961         cubebottom[1].verts[2][0] = 1.0;
962         cubebottom[1].verts[2][1] =-verts_height;
963         cubebottom[1].verts[2][2] =-1.0;        
964         cubebottom[1].u[2] = uv_ratio;
965         cubebottom[1].v[2] = uv_base;
966
967         nfacesbottom = 2;
968
969         //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration
970         //It could be made more efficient for drawing if the triangles were ordered in a strip!
971
972         for(i=0;i<m_resolution;i++){
973                 cubefront.resize(4*nfacesfront);
974                 SplitFace(cubefront,&nfacesfront);
975                 cubetop.resize(4*nfacestop);
976                 SplitFace(cubetop,&nfacestop);
977                 cubebottom.resize(4*nfacesbottom);
978                 SplitFace(cubebottom,&nfacesbottom);    
979                 cubeleft.resize(4*nfacesleft);
980                 SplitFace(cubeleft,&nfacesleft);
981                 cuberight.resize(4*nfacesright);
982                 SplitFace(cuberight,&nfacesright);
983         }
984
985         // Turn into a hemisphere/sphere
986         for(j=0;j<3;j++){
987                 for(i=0;i<nfacesfront;i++)
988                         cubefront[i].verts[j].normalize();
989                 for(i=0;i<nfacestop;i++)
990                         cubetop[i].verts[j].normalize();
991                 for(i=0;i<nfacesbottom;i++)
992                         cubebottom[i].verts[j].normalize();
993                 for(i=0;i<nfacesleft;i++)
994                         cubeleft[i].verts[j].normalize();
995                 for(i=0;i<nfacesright;i++)
996                         cuberight[i].verts[j].normalize();
997         }
998
999         //flatten onto xz plane
1000         for(i=0;i<nfacesfront;i++)
1001                 FlattenDome(cubefront[i].verts);        
1002         for(i=0;i<nfacestop;i++)
1003                 FlattenDome(cubetop[i].verts);
1004         for(i=0;i<nfacesbottom;i++)
1005                 FlattenDome(cubebottom[i].verts);
1006         for(i=0;i<nfacesleft;i++)
1007                 FlattenDome(cubeleft[i].verts);         
1008         for(i=0;i<nfacesright;i++)
1009                 FlattenDome(cuberight[i].verts);
1010 }
1011
1012 void KX_Dome::CreateMeshPanorama(void)
1013 {
1014 /*
1015 1)-  Define the faces of a cube without the top and bottom faces
1016  - each face is made out of 2 triangles
1017 2) Subdivide the faces
1018  - more resolution == more curved lines
1019 3) Spherize the cube
1020  - normalize the verts t
1021 4) Flatten onto xz plane
1022  - use spherical projection techniques to transform the sphere onto a flat panorama
1023 */
1024         int i,j;
1025
1026         float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
1027
1028         /* Top face - two triangles */
1029         cubetop[0].verts[0][0] = -M_SQRT2;
1030         cubetop[0].verts[0][1] = 0.0;
1031         cubetop[0].verts[0][2] = 1.0;
1032         cubetop[0].u[0] = 0.0;
1033         cubetop[0].v[0] = uv_ratio;
1034
1035         cubetop[0].verts[1][0] = 0.0;
1036         cubetop[0].verts[1][1] = M_SQRT2;
1037         cubetop[0].verts[1][2] = 1.0;
1038         cubetop[0].u[1] = 0.0;
1039         cubetop[0].v[1] = 0.0;
1040
1041         //second triangle
1042         cubetop[0].verts[2][0] = M_SQRT2;
1043         cubetop[0].verts[2][1] = 0.0;
1044         cubetop[0].verts[2][2] = 1.0;
1045         cubetop[0].u[2] = uv_ratio;
1046         cubetop[0].v[2] = 0.0;
1047
1048         cubetop[1].verts[0][0] = M_SQRT2;
1049         cubetop[1].verts[0][1] = 0.0;
1050         cubetop[1].verts[0][2] = 1.0;
1051         cubetop[1].u[0] = uv_ratio;
1052         cubetop[1].v[0] = 0.0;
1053
1054         cubetop[1].verts[1][0] = 0.0;
1055         cubetop[1].verts[1][1] = -M_SQRT2;
1056         cubetop[1].verts[1][2] = 1.0;
1057         cubetop[1].u[1] = uv_ratio;
1058         cubetop[1].v[1] = uv_ratio;
1059
1060         cubetop[1].verts[2][0] = -M_SQRT2;
1061         cubetop[1].verts[2][1] = 0.0;
1062         cubetop[1].verts[2][2] = 1.0;
1063         cubetop[1].u[2] = 0.0;
1064         cubetop[1].v[2] = uv_ratio;
1065
1066         nfacestop = 2;
1067
1068         /* Bottom face - two triangles */
1069         cubebottom[0].verts[0][0] = -M_SQRT2;
1070         cubebottom[0].verts[0][1] = 0.0;
1071         cubebottom[0].verts[0][2] = -1.0;
1072         cubebottom[0].u[0] = uv_ratio;
1073         cubebottom[0].v[0] = 0.0;
1074
1075         cubebottom[0].verts[1][0] = M_SQRT2;
1076         cubebottom[0].verts[1][1] = 0.0;
1077         cubebottom[0].verts[1][2] = -1.0;
1078         cubebottom[0].u[1] = 0.0;
1079         cubebottom[0].v[1] = uv_ratio;
1080
1081         cubebottom[0].verts[2][0] = 0.0;
1082         cubebottom[0].verts[2][1] = M_SQRT2;
1083         cubebottom[0].verts[2][2] = -1.0;
1084         cubebottom[0].u[2] = 0.0;
1085         cubebottom[0].v[2] = 0.0;
1086
1087         //second triangle
1088         cubebottom[1].verts[0][0] = M_SQRT2;
1089         cubebottom[1].verts[0][1] = 0.0;
1090         cubebottom[1].verts[0][2] = -1.0;
1091         cubebottom[1].u[0] = 0.0;
1092         cubebottom[1].v[0] = uv_ratio;
1093
1094         cubebottom[1].verts[1][0] = -M_SQRT2;
1095         cubebottom[1].verts[1][1] = 0.0;
1096         cubebottom[1].verts[1][2] = -1.0;
1097         cubebottom[1].u[1] = uv_ratio;
1098         cubebottom[1].v[1] = 0.0;
1099
1100         cubebottom[1].verts[2][0] = 0.0;
1101         cubebottom[1].verts[2][1] = -M_SQRT2;
1102         cubebottom[1].verts[2][2] = -1.0;
1103         cubebottom[1].u[2] = uv_ratio;
1104         cubebottom[1].v[2] = uv_ratio;
1105
1106         nfacesbottom = 2;
1107
1108         /* Left Back (135deg) face - two triangles */
1109
1110         cubeleftback[0].verts[0][0] = 0;
1111         cubeleftback[0].verts[0][1] = -M_SQRT2;
1112         cubeleftback[0].verts[0][2] = -1.0;
1113         cubeleftback[0].u[0] = 0;
1114         cubeleftback[0].v[0] = 0;
1115
1116         cubeleftback[0].verts[1][0] = -M_SQRT2;
1117         cubeleftback[0].verts[1][1] = 0;
1118         cubeleftback[0].verts[1][2] = -1.0;
1119         cubeleftback[0].u[1] = uv_ratio;
1120         cubeleftback[0].v[1] = 0;
1121
1122         cubeleftback[0].verts[2][0] = 0;
1123         cubeleftback[0].verts[2][1] = -M_SQRT2;
1124         cubeleftback[0].verts[2][2] = 1.0;
1125         cubeleftback[0].u[2] = 0;
1126         cubeleftback[0].v[2] = uv_ratio;
1127
1128         //second triangle
1129         cubeleftback[1].verts[0][0] = 0;
1130         cubeleftback[1].verts[0][1] = -M_SQRT2;
1131         cubeleftback[1].verts[0][2] = 1.0;
1132         cubeleftback[1].u[0] = 0;
1133         cubeleftback[1].v[0] = uv_ratio;
1134
1135         cubeleftback[1].verts[1][0] = -M_SQRT2;
1136         cubeleftback[1].verts[1][1] = 0;
1137         cubeleftback[1].verts[1][2] = -1.0;
1138         cubeleftback[1].u[1] = uv_ratio;
1139         cubeleftback[1].v[1] = 0;
1140
1141         cubeleftback[1].verts[2][0] = -M_SQRT2;
1142         cubeleftback[1].verts[2][1] = 0;
1143         cubeleftback[1].verts[2][2] = 1.0;
1144         cubeleftback[1].u[2] = uv_ratio;
1145         cubeleftback[1].v[2] = uv_ratio;
1146
1147         nfacesleftback = 2;
1148
1149         /* Left face - two triangles */
1150         
1151         cubeleft[0].verts[0][0] = -M_SQRT2;
1152         cubeleft[0].verts[0][1] = 0;
1153         cubeleft[0].verts[0][2] = -1.0;
1154         cubeleft[0].u[0] = 0;
1155         cubeleft[0].v[0] = 0;
1156
1157         cubeleft[0].verts[1][0] = 0;
1158         cubeleft[0].verts[1][1] = M_SQRT2;
1159         cubeleft[0].verts[1][2] = -1.0;
1160         cubeleft[0].u[1] = uv_ratio;
1161         cubeleft[0].v[1] = 0;
1162
1163         cubeleft[0].verts[2][0] = -M_SQRT2;
1164         cubeleft[0].verts[2][1] = 0;
1165         cubeleft[0].verts[2][2] = 1.0;
1166         cubeleft[0].u[2] = 0;
1167         cubeleft[0].v[2] = uv_ratio;
1168
1169         //second triangle
1170         cubeleft[1].verts[0][0] = -M_SQRT2;
1171         cubeleft[1].verts[0][1] = 0;
1172         cubeleft[1].verts[0][2] = 1.0;
1173         cubeleft[1].u[0] = 0;
1174         cubeleft[1].v[0] = uv_ratio;
1175
1176         cubeleft[1].verts[1][0] = 0;
1177         cubeleft[1].verts[1][1] = M_SQRT2;
1178         cubeleft[1].verts[1][2] = -1.0;
1179         cubeleft[1].u[1] = uv_ratio;
1180         cubeleft[1].v[1] = 0;
1181
1182         cubeleft[1].verts[2][0] = 0;
1183         cubeleft[1].verts[2][1] = M_SQRT2;
1184         cubeleft[1].verts[2][2] = 1.0;
1185         cubeleft[1].u[2] = uv_ratio;
1186         cubeleft[1].v[2] = uv_ratio;
1187
1188         nfacesleft = 2;
1189         
1190         /* Right face - two triangles */
1191         cuberight[0].verts[0][0] = 0;
1192         cuberight[0].verts[0][1] = M_SQRT2;
1193         cuberight[0].verts[0][2] = -1.0;
1194         cuberight[0].u[0] = 0;
1195         cuberight[0].v[0] = 0;
1196
1197         cuberight[0].verts[1][0] = M_SQRT2;
1198         cuberight[0].verts[1][1] = 0;
1199         cuberight[0].verts[1][2] = -1.0;
1200         cuberight[0].u[1] = uv_ratio;
1201         cuberight[0].v[1] = 0;
1202
1203         cuberight[0].verts[2][0] = M_SQRT2;
1204         cuberight[0].verts[2][1] = 0;
1205         cuberight[0].verts[2][2] = 1.0;
1206         cuberight[0].u[2] = uv_ratio;
1207         cuberight[0].v[2] = uv_ratio;
1208
1209         //second triangle
1210         cuberight[1].verts[0][0] = 0;
1211         cuberight[1].verts[0][1] = M_SQRT2;
1212         cuberight[1].verts[0][2] = -1.0;
1213         cuberight[1].u[0] = 0;
1214         cuberight[1].v[0] = 0;
1215
1216         cuberight[1].verts[1][0] = M_SQRT2;
1217         cuberight[1].verts[1][1] = 0;
1218         cuberight[1].verts[1][2] = 1.0;
1219         cuberight[1].u[1] = uv_ratio;
1220         cuberight[1].v[1] = uv_ratio;
1221
1222         cuberight[1].verts[2][0] = 0;
1223         cuberight[1].verts[2][1] = M_SQRT2;
1224         cuberight[1].verts[2][2] = 1.0;
1225         cuberight[1].u[2] = 0;
1226         cuberight[1].v[2] = uv_ratio;
1227
1228         nfacesright = 2;
1229         
1230         /* Right Back  (-135deg) face - two triangles */
1231         cuberightback[0].verts[0][0] = M_SQRT2;
1232         cuberightback[0].verts[0][1] = 0;
1233         cuberightback[0].verts[0][2] = -1.0;
1234         cuberightback[0].u[0] = 0;
1235         cuberightback[0].v[0] = 0;
1236
1237         cuberightback[0].verts[1][0] = 0;
1238         cuberightback[0].verts[1][1] = -M_SQRT2;
1239         cuberightback[0].verts[1][2] = -1.0;
1240         cuberightback[0].u[1] = uv_ratio;
1241         cuberightback[0].v[1] = 0;
1242
1243         cuberightback[0].verts[2][0] = 0;
1244         cuberightback[0].verts[2][1] = -M_SQRT2;
1245         cuberightback[0].verts[2][2] = 1.0;
1246         cuberightback[0].u[2] = uv_ratio;
1247         cuberightback[0].v[2] = uv_ratio;
1248
1249         //second triangle
1250         cuberightback[1].verts[0][0] = M_SQRT2;
1251         cuberightback[1].verts[0][1] = 0;
1252         cuberightback[1].verts[0][2] = -1.0;
1253         cuberightback[1].u[0] = 0;
1254         cuberightback[1].v[0] = 0;
1255
1256         cuberightback[1].verts[1][0] = 0;
1257         cuberightback[1].verts[1][1] = -M_SQRT2;
1258         cuberightback[1].verts[1][2] = 1.0;
1259         cuberightback[1].u[1] = uv_ratio;
1260         cuberightback[1].v[1] = uv_ratio;
1261
1262         cuberightback[1].verts[2][0] = M_SQRT2;
1263         cuberightback[1].verts[2][1] = 0;
1264         cuberightback[1].verts[2][2] = 1.0;
1265         cuberightback[1].u[2] = 0;
1266         cuberightback[1].v[2] = uv_ratio;
1267
1268         nfacesrightback = 2;
1269
1270         // Subdivide the faces
1271         for(i=0;i<m_resolution;i++)
1272         {
1273                 cubetop.resize(4*nfacestop);
1274                 SplitFace(cubetop,&nfacestop);
1275
1276                 cubebottom.resize(4*nfacesbottom);
1277                 SplitFace(cubebottom,&nfacesbottom);
1278
1279                 cubeleft.resize(4*nfacesleft);
1280                 SplitFace(cubeleft,&nfacesleft);
1281
1282                 cuberight.resize(4*nfacesright);
1283                 SplitFace(cuberight,&nfacesright);
1284
1285                 cubeleftback.resize(4*nfacesleftback);
1286                 SplitFace(cubeleftback,&nfacesleftback);
1287
1288                 cuberightback.resize(4*nfacesrightback);
1289                 SplitFace(cuberightback,&nfacesrightback);
1290         }
1291
1292         // Spherize the cube
1293         for(j=0;j<3;j++)
1294         {
1295                 for(i=0;i<nfacestop;i++)
1296                         cubetop[i].verts[j].normalize();
1297
1298                 for(i=0;i<nfacesbottom;i++)
1299                         cubebottom[i].verts[j].normalize();
1300
1301                 for(i=0;i<nfacesleftback;i++)
1302                         cubeleftback[i].verts[j].normalize();
1303
1304                 for(i=0;i<nfacesleft;i++)
1305                         cubeleft[i].verts[j].normalize();
1306
1307                 for(i=0;i<nfacesright;i++)
1308                         cuberight[i].verts[j].normalize();
1309
1310                 for(i=0;i<nfacesrightback;i++)
1311                         cuberightback[i].verts[j].normalize();
1312         }
1313
1314         //Flatten onto xz plane
1315         for(i=0;i<nfacesleftback;i++)
1316                 FlattenPanorama(cubeleftback[i].verts);
1317
1318         for(i=0;i<nfacesleft;i++)
1319                 FlattenPanorama(cubeleft[i].verts);
1320
1321         for(i=0;i<nfacesright;i++)
1322                 FlattenPanorama(cuberight[i].verts);
1323
1324         for(i=0;i<nfacesrightback;i++)
1325                 FlattenPanorama(cuberightback[i].verts);
1326
1327         for(i=0;i<nfacestop;i++)
1328                 FlattenPanorama(cubetop[i].verts);
1329
1330         for(i=0;i<nfacesbottom;i++)
1331                 FlattenPanorama(cubebottom[i].verts);
1332 }
1333
1334 void KX_Dome::FlattenDome(MT_Vector3 verts[3])
1335 {
1336         double phi, r;
1337
1338         for (int i=0;i<3;i++){
1339                 r = atan2(sqrt(verts[i][0]*verts[i][0] + verts[i][2]*verts[i][2]), verts[i][1]);
1340                 r /= m_radangle/2;
1341
1342                 phi = atan2(verts[i][2], verts[i][0]);
1343
1344                 verts[i][0] = r * cos(phi);
1345                 verts[i][1] = 0;
1346                 verts[i][2] = r * sin(phi);
1347
1348                 if (r > 1.0){
1349                 //round the border
1350                         verts[i][0] = cos(phi);
1351                         verts[i][1] = -3.0;
1352                         verts[i][2] = sin(phi);
1353                 }
1354         }
1355 }
1356
1357 void KX_Dome::FlattenPanorama(MT_Vector3 verts[3])
1358 {
1359 // it creates a full spherical panoramic (360deg)
1360         int i;
1361         double phi;
1362         bool edge=false;
1363
1364         for (i=0;i<3;i++){
1365                 phi = atan2(verts[i][1], verts[i][0]);
1366                 phi *= -1.0; //flipping
1367
1368                 if (phi == -MT_PI) //It's on the edge
1369                         edge=true;
1370
1371                 verts[i][0] = phi / MT_PI;
1372                 verts[i][1] = 0;
1373
1374                 verts[i][2] = atan2(verts[i][2], 1.0);
1375                 verts[i][2] /= MT_PI / 2;
1376         }
1377         if(edge){
1378                 bool right=false;
1379
1380                 for (i=0;i<3;i++){
1381                         if(fmod(verts[i][0],1.0) > 0.0){
1382                                 right=true;
1383                                 break;
1384                         }
1385                 }
1386                 if(right){
1387                         for (i=0;i<3;i++){
1388                                 if(verts[i][0] < 0.0)
1389                                         verts[i][0] *= -1.0;
1390                         }
1391                 }
1392         }
1393 }
1394
1395 void KX_Dome::SplitFace(vector <DomeFace>& face, int *nfaces)
1396 {
1397         int i;
1398         int n1, n2;
1399
1400         n1 = n2 = *nfaces;
1401
1402         for(i=0;i<n1;i++){
1403
1404                 face[n2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2;
1405                 face[n2].verts[1] =  face[i].verts[1];
1406                 face[n2].verts[2] = (face[i].verts[1] + face[i].verts[2]) /2;
1407                 face[n2].u[0]     = (face[i].u[0] + face[i].u[1]) /2;
1408                 face[n2].u[1]     =  face[i].u[1];
1409                 face[n2].u[2]     = (face[i].u[1] + face[i].u[2]) /2;
1410                 face[n2].v[0]     = (face[i].v[0] + face[i].v[1]) /2;
1411                 face[n2].v[1]     =  face[i].v[1];
1412                 face[n2].v[2]     = (face[i].v[1] + face[i].v[2]) /2;
1413
1414                 face[n2+1].verts[0] = (face[i].verts[1] + face[i].verts[2]) /2;
1415                 face[n2+1].verts[1] =  face[i].verts[2];
1416                 face[n2+1].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2;
1417                 face[n2+1].u[0]         = (face[i].u[1] + face[i].u[2]) /2;
1418                 face[n2+1].u[1]         =  face[i].u[2];
1419                 face[n2+1].u[2]         = (face[i].u[2] + face[i].u[0]) /2;
1420                 face[n2+1].v[0]         = (face[i].v[1] + face[i].v[2]) /2;
1421                 face[n2+1].v[1]         =  face[i].v[2];
1422                 face[n2+1].v[2]         = (face[i].v[2] + face[i].v[0]) /2;
1423
1424                 face[n2+2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2;
1425                 face[n2+2].verts[1] = (face[i].verts[1] + face[i].verts[2]) /2;
1426                 face[n2+2].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2;
1427                 face[n2+2].u[0]   = (face[i].u[0] + face[i].u[1]) /2;
1428                 face[n2+2].u[1]   = (face[i].u[1] + face[i].u[2]) /2;
1429                 face[n2+2].u[2]   = (face[i].u[2] + face[i].u[0]) /2;
1430                 face[n2+2].v[0]   = (face[i].v[0] + face[i].v[1]) /2;
1431                 face[n2+2].v[1]   = (face[i].v[1] + face[i].v[2]) /2;
1432                 face[n2+2].v[2]   = (face[i].v[2] + face[i].v[0]) /2;           
1433
1434                 //face[i].verts[0] = face[i].verts[0] ;
1435                 face[i].verts[1] = (face[i].verts[0] + face[i].verts[1]) /2;
1436                 face[i].verts[2] = (face[i].verts[0] + face[i].verts[2]) /2;
1437                 //face[i].u[0]   =  face[i].u[0];
1438                 face[i].u[1]     = (face[i].u[0] + face[i].u[1]) /2;
1439                 face[i].u[2]     = (face[i].u[0] + face[i].u[2]) /2;
1440                 //face[i].v[0]   = face[i].v[0] ;
1441                 face[i].v[1]     = (face[i].v[0] + face[i].v[1]) /2;
1442                 face[i].v[2]     = (face[i].v[0] + face[i].v[2]) /2;            
1443
1444                 n2 += 3; // number of faces
1445         }
1446         *nfaces = n2;
1447 }
1448
1449 void KX_Dome::CalculateFrustum(KX_Camera * cam)
1450 {
1451         /*
1452         // manually creating a 90deg Field of View Frustum 
1453
1454         the original formula:
1455         top = tan(fov*3.14159/360.0) * near [for fov in degrees]
1456         fov*0.5 = arctan ((top-bottom)*0.5 / near) [for fov in radians]
1457         bottom = -top
1458         left = aspect * bottom
1459         right = aspect * top
1460
1461         // the equivalent GLU call is:
1462         glMatrixMode(GL_PROJECTION);
1463         glLoadIdentity();
1464         gluPerspective(90.0,1.0,cam->GetCameraNear(),cam->GetCameraFar());
1465         */
1466
1467         RAS_FrameFrustum m_frustrum; //90 deg. Frustum
1468
1469         m_frustrum.camnear = cam->GetCameraNear();
1470         m_frustrum.camfar = cam->GetCameraFar();
1471
1472 //      float top = tan(90.0*MT_PI/360.0) * m_frustrum.camnear;
1473         float top = m_frustrum.camnear; // for deg = 90deg, tan = 1
1474
1475         m_frustrum.x1 = -top;
1476         m_frustrum.x2 = top;
1477         m_frustrum.y1 = -top;
1478         m_frustrum.y2 = top;
1479         
1480         m_projmat = m_rasterizer->GetFrustumMatrix(
1481         m_frustrum.x1, m_frustrum.x2, m_frustrum.y1, m_frustrum.y2, m_frustrum.camnear, m_frustrum.camfar);
1482
1483 }
1484
1485 void KX_Dome::CalculateCameraOrientation()
1486 {
1487 /*
1488 Uses 4 cameras for angles up to 180deg
1489 Uses 5 cameras for angles up to 250deg
1490 Uses 6 cameras for angles up to 360deg
1491 */
1492         int i;
1493         float deg45 = MT_PI / 4;
1494         MT_Scalar c = cos(deg45);
1495         MT_Scalar s = sin(deg45);
1496
1497         if (m_angle <= 180 && (m_mode == DOME_FISHEYE 
1498                 || m_mode == DOME_TRUNCATED_FRONT
1499                 || m_mode == DOME_TRUNCATED_REAR)){
1500
1501                 m_locRot[0] = MT_Matrix3x3( // 90deg - Top
1502                                                 c, -s, 0.0,
1503                                                 0.0,0.0, -1.0,
1504                                                 s, c, 0.0);
1505
1506                 m_locRot[1] = MT_Matrix3x3( // 90deg - Bottom
1507                                                 -s, c, 0.0,
1508                                                 0.0,0.0, 1.0,
1509                                                 s, c, 0.0);
1510
1511                 m_locRot[2] = MT_Matrix3x3( // 45deg - Left
1512                                                 c, 0.0, s,
1513                                                 0, 1.0, 0.0,
1514                                                 -s, 0.0, c);
1515
1516                 m_locRot[3] = MT_Matrix3x3( // 45deg - Right
1517                                                 c, 0.0, -s,
1518                                                 0.0, 1.0, 0.0,
1519                                                 s, 0.0, c);
1520
1521         } else if (m_mode == DOME_ENVMAP || (m_angle > 180 && (m_mode == DOME_FISHEYE
1522                 || m_mode == DOME_TRUNCATED_FRONT 
1523                 || m_mode == DOME_TRUNCATED_REAR))){
1524
1525                 m_locRot[0] = MT_Matrix3x3( // 90deg - Top
1526                                                  1.0, 0.0, 0.0,
1527                                                  0.0, 0.0,-1.0,
1528                                                  0.0, 1.0, 0.0);
1529
1530                 m_locRot[1] = MT_Matrix3x3( // 90deg - Bottom
1531                                                  1.0, 0.0, 0.0,
1532                                                  0.0, 0.0, 1.0,
1533                                                  0.0,-1.0, 0.0);
1534
1535                 m_locRot[2] = MT_Matrix3x3( // -90deg - Left
1536                                                  0.0, 0.0, 1.0,
1537                                                  0.0, 1.0, 0.0,
1538                                                  -1.0, 0.0, 0.0);
1539
1540                 m_locRot[3] = MT_Matrix3x3( // 90deg - Right
1541                                                  0.0, 0.0,-1.0,
1542                                                  0.0, 1.0, 0.0,
1543                                                  1.0, 0.0, 0.0);
1544                                                 
1545                 m_locRot[4] = MT_Matrix3x3( // 0deg - Front
1546                                                 1.0, 0.0, 0.0,
1547                                                 0.0, 1.0, 0.0,
1548                                                 0.0, 0.0, 1.0);
1549
1550                 m_locRot[5] = MT_Matrix3x3( // 180deg - Back - USED for ENVMAP only
1551                                                 -1.0, 0.0, 0.0,
1552                                                  0.0, 1.0, 0.0,
1553                                                  0.0, 0.0,-1.0);
1554
1555         } else if (m_mode == DOME_PANORAM_SPH){
1556
1557                 m_locRot[0] = MT_Matrix3x3( // Top 
1558                                                 c, s, 0.0,
1559                                                 0.0,0.0, -1.0,
1560                                                 -s, c, 0.0);
1561
1562                 m_locRot[1] = MT_Matrix3x3( // Bottom
1563                                                 c, s, 0.0,
1564                                                 0.0 ,0.0, 1.0,
1565                                                 s, -c, 0.0);
1566
1567                 m_locRot[2] = MT_Matrix3x3( // 45deg - Left
1568                                                 -s, 0.0, c,
1569                                                 0, 1.0, 0.0,
1570                                                 -c, 0.0, -s);
1571
1572                 m_locRot[3] = MT_Matrix3x3( // 45deg - Right
1573                                                 c, 0.0, s,
1574                                                 0, 1.0, 0.0,
1575                                                 -s, 0.0, c);
1576
1577                 m_locRot[4] = MT_Matrix3x3( // 135deg - LeftBack
1578                                                 -s, 0.0, -c,
1579                                                 0.0, 1.0, 0.0,
1580                                                 c, 0.0, -s);
1581
1582                 m_locRot[5] = MT_Matrix3x3( // 135deg - RightBack
1583                                                 c, 0.0, -s,
1584                                                 0.0, 1.0, 0.0,
1585                                                 s, 0.0, c);
1586         }
1587
1588         // rotating the camera in horizontal axis
1589         if (m_tilt)
1590         {
1591                 float tiltdeg = ((m_tilt % 360) * 2 * MT_PI) / 360;
1592                 c = cos(tiltdeg);
1593                 s = sin(tiltdeg);
1594
1595                 MT_Matrix3x3 tilt_mat = MT_Matrix3x3(
1596                 1.0, 0.0, 0.0,
1597                 0.0, c, -s,
1598                 0.0, s,  c
1599                 );
1600
1601                 for (i =0;i<6;i++)
1602                         m_locRot[i] = tilt_mat * m_locRot[i];
1603         }
1604 }
1605
1606 void KX_Dome::RotateCamera(KX_Camera* cam, int i)
1607 {
1608 // I'm not using it, I'm doing inline calls for these commands
1609 // but it's nice to have it here in case I need it
1610
1611         MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation();
1612
1613         cam->NodeSetLocalOrientation(camori*m_locRot[i]);
1614         cam->NodeUpdateGS(0.f);
1615
1616         MT_Transform camtrans(cam->GetWorldToCamera());
1617         MT_Matrix4x4 viewmat(camtrans);
1618         m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
1619         cam->SetModelviewMatrix(viewmat);
1620
1621         // restore the original orientation
1622         cam->NodeSetLocalOrientation(camori);
1623         cam->NodeUpdateGS(0.f);
1624 }
1625
1626 void KX_Dome::Draw(void)
1627 {
1628
1629         if (fboSupported){
1630                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
1631
1632                 glViewport(0,0,warp.imagesize, warp.imagesize);
1633                 glScissor(0,0,warp.imagesize, warp.imagesize);
1634         }
1635
1636         switch(m_mode){
1637                 case DOME_FISHEYE:
1638                         DrawDomeFisheye();
1639                         break;
1640                 case DOME_ENVMAP:
1641                         DrawEnvMap();
1642                         break;
1643                 case DOME_PANORAM_SPH:
1644                         DrawPanorama();
1645                         break;
1646                 case DOME_TRUNCATED_FRONT:
1647                         DrawDomeFisheye();
1648                         break;
1649                 case DOME_TRUNCATED_REAR:
1650                         DrawDomeFisheye();
1651                         break;
1652         }
1653
1654         if(warp.usemesh)
1655         {
1656                 if(fboSupported)
1657                 {
1658                         m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
1659                         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1660                 }
1661                 else
1662                 {
1663                         glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
1664                         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight);
1665                 }
1666                 DrawDomeWarped();
1667         }
1668 }
1669
1670 void KX_Dome::DrawEnvMap(void)
1671 {
1672         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1673         glMatrixMode(GL_PROJECTION);
1674         glLoadIdentity();
1675
1676         // Making the viewport always square 
1677
1678         int can_width = m_viewport.GetRight();
1679         int can_height = m_viewport.GetTop();
1680
1681         float ortho_width, ortho_height;
1682
1683         if (warp.usemesh)
1684                 glOrtho((-1.0), 1.0, (-0.66), 0.66, -20.0, 10.0); //stretch the image to reduce resolution lost
1685
1686         else {
1687                 if (can_width/3 <= can_height/2){
1688                         ortho_width = 1.0;
1689                         ortho_height = (float)can_height/can_width;
1690                 }else{
1691                         ortho_height = 2.0f / 3;
1692                         ortho_width = (float)can_width/can_height * ortho_height;
1693                 }
1694                 
1695                 glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
1696         }
1697
1698         glMatrixMode(GL_TEXTURE);
1699         glLoadIdentity();
1700         glMatrixMode(GL_MODELVIEW);
1701         glLoadIdentity();
1702         gluLookAt(0.0,0.0,1.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
1703
1704         glPolygonMode(GL_FRONT, GL_FILL);
1705         glShadeModel(GL_SMOOTH);
1706         glDisable(GL_LIGHTING);
1707         glDisable(GL_DEPTH_TEST);
1708
1709         glEnable(GL_TEXTURE_2D);
1710         glColor3f(1.0,1.0,1.0);
1711
1712         float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
1713         double onebythree = 1.0f / 3;
1714
1715         // domefacesId[0] =>  (top)
1716         glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
1717         glBegin(GL_QUADS);
1718                 glTexCoord2f(uv_ratio,uv_ratio);
1719                 glVertex3f( onebythree, 0.0f, 3.0f);
1720                 glTexCoord2f(0.0,uv_ratio);
1721                 glVertex3f(-onebythree, 0.0f, 3.0f);
1722                 glTexCoord2f(0.0,0.0);
1723                 glVertex3f(-onebythree,-2 * onebythree, 3.0f);
1724                 glTexCoord2f(uv_ratio,0.0);
1725                 glVertex3f(onebythree,-2 * onebythree, 3.0f);
1726         glEnd();
1727
1728         // domefacesId[1] =>  (bottom)
1729         glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
1730         glBegin(GL_QUADS);
1731                 glTexCoord2f(uv_ratio,uv_ratio);
1732                 glVertex3f(-onebythree, 0.0f, 3.0f);
1733                 glTexCoord2f(0.0,uv_ratio);
1734                 glVertex3f(-1.0f, 0.0f, 3.0f);
1735                 glTexCoord2f(0.0,0.0);
1736                 glVertex3f(-1.0f,-2 * onebythree, 3.0f);
1737                 glTexCoord2f(uv_ratio,0.0);
1738                 glVertex3f(-onebythree,-2 * onebythree, 3.0f);
1739         glEnd();
1740
1741         // domefacesId[2] => -90deg (left)
1742         glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
1743         glBegin(GL_QUADS);
1744                 glTexCoord2f(uv_ratio,uv_ratio);
1745                 glVertex3f(-onebythree, 2 * onebythree, 3.0f);
1746                 glTexCoord2f(0.0,uv_ratio);
1747                 glVertex3f(-1.0f, 2 * onebythree, 3.0f);
1748                 glTexCoord2f(0.0,0.0);
1749                 glVertex3f(-1.0f, 0.0f, 3.0f);
1750                 glTexCoord2f(uv_ratio,0.0);
1751                 glVertex3f(-onebythree, 0.0f, 3.0f);
1752         glEnd();
1753
1754         // domefacesId[3] => 90deg (right)
1755         glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
1756         glBegin(GL_QUADS);
1757                 glTexCoord2f(uv_ratio,uv_ratio);
1758                 glVertex3f( 1.0f, 2 * onebythree, 3.0f);
1759                 glTexCoord2f(0.0,uv_ratio);
1760                 glVertex3f( onebythree, 2 * onebythree, 3.0f);
1761                 glTexCoord2f(0.0,0.0);
1762                 glVertex3f( onebythree, 0.0f, 3.0f);
1763                 glTexCoord2f(uv_ratio,0.0);
1764                 glVertex3f(1.0f, 0.0f, 3.0f);
1765         glEnd();
1766
1767         // domefacesId[4] => 0deg (front)
1768         glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
1769         glBegin(GL_QUADS);
1770                 glTexCoord2f(uv_ratio,uv_ratio);
1771                 glVertex3f( 1.0f, 0.0f, 3.0f);
1772                 glTexCoord2f(0.0,uv_ratio);
1773                 glVertex3f( onebythree, 0.0f, 3.0f);
1774                 glTexCoord2f(0.0,0.0);
1775                 glVertex3f( onebythree,-2 * onebythree, 3.0f);
1776                 glTexCoord2f(uv_ratio,0.0);
1777                 glVertex3f(1.0f, -2 * onebythree, 3.0f);
1778         glEnd();
1779
1780         // domefacesId[5] => 180deg (back)
1781         glBindTexture(GL_TEXTURE_2D, domefacesId[5]);
1782         glBegin(GL_QUADS);
1783                 glTexCoord2f(uv_ratio,uv_ratio);
1784                 glVertex3f( onebythree, 2 * onebythree, 3.0f);
1785                 glTexCoord2f(0.0,uv_ratio);
1786                 glVertex3f(-onebythree, 2 * onebythree, 3.0f);
1787                 glTexCoord2f(0.0,0.0);
1788                 glVertex3f(-onebythree, 0.0f, 3.0f);
1789                 glTexCoord2f(uv_ratio,0.0);
1790                 glVertex3f(onebythree, 0.0f, 3.0f);
1791         glEnd();
1792
1793         glDisable(GL_TEXTURE_2D);
1794         glEnable(GL_DEPTH_TEST);
1795 }
1796
1797 void KX_Dome::DrawDomeFisheye(void)
1798 {
1799         int i;
1800
1801         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1802         glMatrixMode(GL_PROJECTION);
1803         glLoadIdentity();
1804
1805         // Making the viewport always square 
1806
1807         int can_width = m_viewport.GetRight();
1808         int can_height = m_viewport.GetTop();
1809
1810         float ortho_width, ortho_height;
1811
1812         if(m_mode == DOME_FISHEYE) {
1813                 if (warp.usemesh)
1814                         glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost
1815
1816                 else {
1817                         if (can_width < can_height){
1818                                 ortho_width = 1.0;
1819                                 ortho_height = (float)can_height/can_width;
1820                         }else{
1821                                 ortho_width = (float)can_width/can_height;
1822                                 ortho_height = 1.0;
1823                         }
1824                         
1825                         glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
1826                 }
1827         }
1828         else if(m_mode == DOME_TRUNCATED_FRONT)
1829         {
1830                 ortho_width = 1.0;
1831                 ortho_height = 2 * ((float)can_height/can_width) - 1.0 ;
1832
1833                 glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0);
1834         }
1835         else { //m_mode == DOME_TRUNCATED_REAR
1836                 ortho_width = 1.0;
1837                 ortho_height = 2 * ((float)can_height/can_width) - 1.0 ;
1838
1839                 glOrtho((-ortho_width), ortho_width, (-ortho_width), ortho_height, -20.0, 10.0);
1840         }
1841
1842         glMatrixMode(GL_TEXTURE);
1843         glLoadIdentity();
1844         glMatrixMode(GL_MODELVIEW);
1845         glLoadIdentity();
1846         gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0);
1847
1848         if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
1849                 glPolygonMode(GL_FRONT, GL_LINE);
1850         else
1851                 glPolygonMode(GL_FRONT, GL_FILL);
1852
1853         glShadeModel(GL_SMOOTH);
1854         glDisable(GL_LIGHTING);
1855         glDisable(GL_DEPTH_TEST);
1856
1857         glEnable(GL_TEXTURE_2D);
1858         glColor3f(1.0,1.0,1.0);
1859
1860         if (dlistSupported){
1861                 for(i=0;i<m_numfaces;i++){
1862                         glBindTexture(GL_TEXTURE_2D, domefacesId[i]);
1863                         glCallList(dlistId+i);
1864                 }
1865         }
1866         else { // DisplayLists not supported
1867                 // top triangle
1868                 glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
1869                 GLDrawTriangles(cubetop, nfacestop);
1870
1871                 // bottom triangle      
1872                 glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
1873                 GLDrawTriangles(cubebottom, nfacesbottom);
1874
1875                 // left triangle
1876                 glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
1877                 GLDrawTriangles(cubeleft, nfacesleft);
1878
1879                 // right triangle
1880                 glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
1881                 GLDrawTriangles(cuberight, nfacesright);
1882
1883                 if (m_angle > 180){
1884                         // front triangle
1885                         glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
1886                         GLDrawTriangles(cubefront, nfacesfront);
1887                 }
1888         }
1889         glDisable(GL_TEXTURE_2D);
1890         glEnable(GL_DEPTH_TEST);
1891 }
1892
1893 void KX_Dome::DrawPanorama(void)
1894 {
1895         int i;
1896         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1897         glMatrixMode(GL_PROJECTION);
1898         glLoadIdentity();
1899
1900         // Making the viewport always square 
1901
1902         int can_width = m_viewport.GetRight();
1903         int can_height = m_viewport.GetTop();
1904
1905         float ortho_height = 1.0;
1906         float ortho_width = 1.0;
1907
1908         if (warp.usemesh)
1909                 glOrtho((-1.0), 1.0, (-0.5), 0.5, -20.0, 10.0); //stretch the image to reduce resolution lost
1910
1911         else {
1912                 //using all the screen
1913                 if ((can_width / 2) <= (can_height)){
1914                         ortho_width = 1.0;
1915                         ortho_height = (float)can_height/can_width;
1916                 }else{
1917                         ortho_width = (float)can_width/can_height * 0.5;
1918                         ortho_height = 0.5;
1919                 }
1920                 
1921                 glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
1922         }
1923
1924         glMatrixMode(GL_TEXTURE);
1925         glLoadIdentity();
1926         glMatrixMode(GL_MODELVIEW);
1927         glLoadIdentity();
1928         gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0);
1929
1930         if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
1931                 glPolygonMode(GL_FRONT, GL_LINE);
1932         else
1933                 glPolygonMode(GL_FRONT, GL_FILL);
1934
1935         glShadeModel(GL_SMOOTH);
1936         glDisable(GL_LIGHTING);
1937         glDisable(GL_DEPTH_TEST);
1938
1939         glEnable(GL_TEXTURE_2D);
1940         glColor3f(1.0,1.0,1.0);
1941
1942         if (dlistSupported){
1943                 for(i=0;i<m_numfaces;i++){
1944                         glBindTexture(GL_TEXTURE_2D, domefacesId[i]);
1945                         glCallList(dlistId+i);
1946                 }
1947         }
1948         else {
1949                 // domefacesId[4] =>  (top)
1950                 glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
1951                         GLDrawTriangles(cubetop, nfacestop);
1952
1953                 // domefacesId[5] =>  (bottom)
1954                 glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
1955                         GLDrawTriangles(cubebottom, nfacesbottom);
1956
1957                 // domefacesId[1] => -45deg (left)
1958                 glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
1959                         GLDrawTriangles(cubeleft, nfacesleft);
1960
1961                 // domefacesId[2] => 45deg (right)
1962                 glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
1963                         GLDrawTriangles(cuberight, nfacesright);
1964
1965                 // domefacesId[0] => -135deg (leftback)
1966                 glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
1967                         GLDrawTriangles(cubeleftback, nfacesleftback);
1968
1969                 // domefacesId[3] => 135deg (rightback)
1970                 glBindTexture(GL_TEXTURE_2D, domefacesId[5]);
1971                         GLDrawTriangles(cuberightback, nfacesrightback);
1972         }
1973         glDisable(GL_TEXTURE_2D);
1974         glEnable(GL_DEPTH_TEST);
1975 }
1976
1977 void KX_Dome::DrawDomeWarped(void)
1978 {
1979         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1980         glMatrixMode(GL_PROJECTION);
1981         glLoadIdentity();
1982
1983         // Making the viewport always square 
1984         int can_width = m_viewport.GetRight();
1985         int can_height = m_viewport.GetTop();
1986
1987         double screen_ratio = can_width/ (double) can_height;
1988
1989         glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0);
1990
1991
1992         glMatrixMode(GL_TEXTURE);
1993         glLoadIdentity();
1994         glMatrixMode(GL_MODELVIEW);
1995         glLoadIdentity();
1996         gluLookAt(0.0, 0.0, 1.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
1997
1998         if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
1999                 glPolygonMode(GL_FRONT, GL_LINE);
2000         else
2001                 glPolygonMode(GL_FRONT, GL_FILL);
2002
2003         glShadeModel(GL_SMOOTH);
2004         glDisable(GL_LIGHTING);
2005         glDisable(GL_DEPTH_TEST);
2006
2007         glEnable(GL_TEXTURE_2D);
2008         glColor3f(1.0,1.0,1.0);
2009
2010         if (dlistSupported){
2011                 glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
2012                 glCallList(dlistId + m_numfaces);
2013         }
2014         else{
2015                 glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
2016                 GLDrawWarpQuads();
2017         }
2018         glDisable(GL_TEXTURE_2D);
2019         glEnable(GL_DEPTH_TEST);
2020 }
2021
2022 void KX_Dome::BindImages(int i)
2023 {
2024         glBindTexture(GL_TEXTURE_2D, domefacesId[i]);
2025         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), m_buffersize, m_buffersize);
2026 }
2027
2028 void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
2029 {
2030         if (!cam)
2031                 return;
2032
2033         m_canvas->SetViewPort(0,0,m_buffersize-1,m_buffersize-1);
2034
2035 //      m_rasterizer->SetAmbient();
2036         m_rasterizer->DisplayFog();
2037
2038         CalculateFrustum(cam); //calculates m_projmat
2039         cam->SetProjectionMatrix(m_projmat);
2040         m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
2041 //      Dome_RotateCamera(cam,i);
2042
2043         MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation();
2044
2045         cam->NodeSetLocalOrientation(camori*m_locRot[i]);
2046         cam->NodeUpdateGS(0.f);
2047
2048         MT_Transform camtrans(cam->GetWorldToCamera());
2049         MT_Matrix4x4 viewmat(camtrans);
2050         m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), 1.0);
2051         cam->SetModelviewMatrix(viewmat);
2052
2053         // restore the original orientation
2054         cam->NodeSetLocalOrientation(camori);
2055         cam->NodeUpdateGS(0.f);
2056
2057         scene->CalculateVisibleMeshes(m_rasterizer,cam);
2058         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
2059 }
2060