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