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