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