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