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