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