Improved OpenGL Shader Language support for game engine. The python interface is...
[blender-staging.git] / source / gameengine / Ketsji / BL_Texture.cpp
1 // ------------------------------------
2 #ifdef WIN32
3 #include <windows.h>
4 #endif // WIN32
5 #ifdef __APPLE__
6 #define GL_GLEXT_LEGACY 1
7 #include <OpenGL/gl.h>
8 #include <OpenGL/glu.h>
9 #else
10 #include <GL/gl.h>
11 #include <GL/glu.h>
12 #endif
13
14 #include <iostream>
15
16 #include "BL_Material.h"
17 #include "BL_Texture.h"
18 #include "MT_assert.h"
19
20 #include "DNA_texture_types.h"
21 #include "DNA_image_types.h"
22 #include "IMB_imbuf_types.h"
23 #include "BKE_image.h"
24 #include "BLI_blenlib.h"
25
26 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
27 #include "RAS_OpenGLRasterizer/ARB_multitexture.h"
28 #include "RAS_ICanvas.h"
29 #include "RAS_Rect.h"
30
31 #include "KX_GameObject.h"
32
33 using namespace bgl;
34
35 #define spit(x) std::cout << x << std::endl;
36
37 #include "MEM_guardedalloc.h"
38
39 extern "C" {
40         // envmaps
41         #include "IMB_imbuf.h"
42         void my_envmap_split_ima(EnvMap *env);
43         void my_free_envmapdata(EnvMap *env);
44 }
45
46 // (n&(n-1)) zeros the least significant bit of n 
47 static int is_pow2(int num) {
48         return ((num)&(num-1))==0;
49 }
50 static int smaller_pow2(int num) {
51         while (!is_pow2(num))
52                 num= num&(num-1);
53         return num;     
54 }
55
56 BL_Texture::BL_Texture()
57 :       mTexture(0),
58         mError(0),
59         mOk(0),
60         mNeedsDeleted(0),
61         mType(0),
62         mName(""),
63         mUnit(0)
64 {
65         // --
66 }
67
68 BL_Texture::~BL_Texture()
69 {
70         // --
71 }
72
73 void BL_Texture::DeleteTex()
74 {
75         if( mNeedsDeleted ) {
76                 glDeleteTextures(1, (GLuint*)&mTexture);
77                 mNeedsDeleted = 0;
78                 mOk = 0;
79         }
80 }
81
82
83 bool BL_Texture::InitFromImage(int unit,  Image *img, bool mipmap)
84 {
85         if(!img || img->ok==0 ) {
86                 mError = true;
87                 mOk = false;
88                 return mOk;
89         }
90         if( img->ibuf==0 ) {
91                 load_image(img, IB_rect, "", 0);
92                 if(img->ibuf==0) {
93                         img->ok = 0;
94                         mError = true;
95                         mOk = false;
96                         return mOk;
97                 } 
98         }
99         mTexture = img->bindcode;
100
101         mName = img->id.name;
102         mType = GL_TEXTURE_2D;
103         mUnit = unit;
104
105         // smoke em if we got em
106         if (mTexture != 0) {
107                 glBindTexture(GL_TEXTURE_2D, mTexture );
108                 Validate();
109                 return mOk;
110         }
111         mNeedsDeleted = 1;
112         glGenTextures(1, (GLuint*)&mTexture);
113         InitGLTex(img->ibuf->rect, img->ibuf->x, img->ibuf->y, mipmap);
114         Validate();
115         return mOk;
116 }
117
118 void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
119 {
120         if (!is_pow2(x) || !is_pow2(y) ) {
121                 InitNonPow2Tex(pix, x,y,mipmap);
122                 return;
123         }
124
125         glBindTexture(GL_TEXTURE_2D, mTexture );
126         if( mipmap ) {
127                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
128                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
129                 gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix );
130         } 
131         else {
132                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
133                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
134                 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix );
135         }
136
137         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
138 }
139
140
141 void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
142 {
143         int nx= smaller_pow2(x);
144         int ny= smaller_pow2(y);
145
146         unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int));
147         
148         gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels);
149         glBindTexture(GL_TEXTURE_2D, mTexture );
150
151         if( mipmap ) {
152                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
153                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
154                 gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
155         }
156         else {
157                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
158                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
159                 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
160         }
161         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
162         free(newPixels);
163 }
164
165
166 bool BL_Texture::InitCubeMap(int unit,  EnvMap *cubemap )
167 {
168 #ifdef GL_ARB_texture_cube_map
169         if(!RAS_EXT_support._ARB_texture_cube_map) {
170                 spit("cubemaps not supported");
171                 mError = true;
172                 mOk = false;
173                 return mOk;
174         }
175         
176         else if(!cubemap || cubemap->ima->ok==0 ) {
177                 mError = true;
178                 mOk = false;
179                 return mOk;
180         }
181
182         if( cubemap->ima->ibuf==0 )  {
183                 load_image(cubemap->ima, IB_rect, "", 0);
184                 if(cubemap->ima->ibuf==0) {
185                         cubemap->ima->ok = 0;
186                         mError = true;
187                         mOk = false;
188                         return mOk;
189                 }
190         }
191
192         EnvMap *CubeMap = cubemap;
193         mNeedsDeleted = 1;
194         mType = GL_TEXTURE_CUBE_MAP_ARB;
195         mTexture = 0;
196         mName = CubeMap->ima->id.name;
197         mUnit = unit;
198
199
200         glGenTextures(1, (GLuint*)&mTexture);
201         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture );
202         bool needs_split = false;
203
204         if(!CubeMap->cube[0]) needs_split = true; 
205
206         if(needs_split){
207                 // split it
208                 my_envmap_split_ima(CubeMap);
209         }
210
211         int x = CubeMap->ima->ibuf->x;
212         int y = CubeMap->ima->ibuf->y;
213
214         // -----------------------------------
215         x       = CubeMap->cube[0]->ibuf->x;
216         y       = CubeMap->cube[0]->ibuf->y;
217
218         // check the first image, and assume the rest
219         if (!is_pow2(x) || !is_pow2(y)) {
220                 spit("invalid envmap size please render with CubeRes @ power of two");
221                 my_free_envmapdata(CubeMap);
222                 mError = true;
223                 mOk = false;
224                 return mOk;
225         }
226         /* 
227         */
228
229 #define SetCubeMapFace(face, num)       \
230         glTexImage2D(face, 0,GL_RGBA,   \
231         CubeMap->cube[num]->ibuf->x,    \
232         CubeMap->cube[num]->ibuf->y,    \
233         0, GL_RGBA, GL_UNSIGNED_BYTE,   \
234         CubeMap->cube[num]->ibuf->rect)
235
236         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5);
237         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3);
238         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0);
239         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1);
240         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2);
241         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4);
242
243         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
244         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
245         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S,     GL_REPEAT );
246         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T,     GL_REPEAT );
247         
248                 
249         if(needs_split) {
250                 cubemap->ima = CubeMap->ima;
251                 my_free_envmapdata(CubeMap);
252         }
253
254         mOk = IsValid();
255         return mOk;
256
257 #else
258
259         mError = true;
260         mOk = false;
261         return mOk;
262
263 #endif//GL_ARB_texture_cube_map
264 }
265
266
267 STR_String BL_Texture::GetName() const
268 {
269         return mName;
270 }
271
272
273 bool BL_Texture::IsValid()
274 {
275         return (mTexture!= 0)?glIsTexture(mTexture)!=0:false;
276 }
277
278
279 void BL_Texture::Validate()
280 {
281         mOk = IsValid();
282 }
283
284
285 bool BL_Texture::Ok()
286 {
287         return  (mTexture!= 0); 
288 }
289
290
291 unsigned int BL_Texture::GetTextureType() const
292 {
293         return mType;
294 }
295
296 int BL_Texture::GetMaxUnits()
297 {
298         GLint unit=0;
299 #ifdef GL_ARB_multitexture
300         if(RAS_EXT_support._ARB_multitexture) {
301                 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
302                 return (MAXTEX>=unit?unit:MAXTEX);
303         }
304 #endif
305         return 0;
306 }
307
308 void BL_Texture::ActivateFirst()
309 {
310 #ifdef GL_ARB_multitexture
311         if(RAS_EXT_support._ARB_multitexture)
312                 bgl::blActiveTextureARB(GL_TEXTURE0_ARB);
313 #endif
314 }
315
316 void BL_Texture::ActivateUnit(int unit)
317 {
318 #ifdef GL_ARB_multitexture
319         if(RAS_EXT_support._ARB_multitexture) {
320                 if(unit <= MAXTEX)
321                         bgl::blActiveTextureARB(GL_TEXTURE0_ARB+unit);
322         }
323 #endif
324 }
325
326
327 void BL_Texture::DisableUnit()
328 {
329 #ifdef GL_ARB_multitexture
330         if(RAS_EXT_support._ARB_multitexture)
331                 bgl::blActiveTextureARB(GL_TEXTURE0_ARB+mUnit);
332 #endif
333         glMatrixMode(GL_TEXTURE);
334         glLoadIdentity();
335         glMatrixMode(GL_MODELVIEW);
336
337 #ifdef GL_ARB_texture_cube_map
338         if(RAS_EXT_support._ARB_texture_cube_map)
339                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
340 #endif
341         glDisable(GL_TEXTURE_2D);
342         glDisable(GL_TEXTURE_GEN_S);
343         glDisable(GL_TEXTURE_GEN_T);
344         glDisable(GL_TEXTURE_GEN_R);
345         glDisable(GL_TEXTURE_GEN_Q);
346         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
347 }
348
349
350 void BL_Texture::DisableAllTextures()
351 {
352 #ifdef GL_ARB_multitexture
353         glDisable(GL_BLEND);
354         for(int i=0; i<MAXTEX; i++) {
355                 if(RAS_EXT_support._ARB_multitexture)
356                         bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i);
357                 glMatrixMode(GL_TEXTURE);
358                 glLoadIdentity();
359                 glMatrixMode(GL_MODELVIEW);
360 #ifdef GL_ARB_texture_cube_map
361                 if(RAS_EXT_support._ARB_texture_cube_map)
362                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
363 #endif//GL_ARB_texture_cube_map
364                 glDisable(GL_TEXTURE_2D);       
365                 glDisable(GL_TEXTURE_GEN_S);
366                 glDisable(GL_TEXTURE_GEN_T);
367                 glDisable(GL_TEXTURE_GEN_R);
368                 glDisable(GL_TEXTURE_GEN_Q);
369                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
370         }
371 #endif
372 }
373
374
375 void BL_Texture::ActivateTexture()
376 {
377 #ifdef GL_ARB_multitexture
378         if(RAS_EXT_support._ARB_multitexture)
379                 bgl::blActiveTextureARB(GL_TEXTURE0_ARB+mUnit);
380 #ifdef GL_ARB_texture_cube_map
381         if(mType == GL_TEXTURE_CUBE_MAP_ARB && RAS_EXT_support._ARB_texture_cube_map ) {
382                 glDisable(GL_TEXTURE_2D);
383                 glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture );     
384                 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
385         } else
386 #endif
387         {
388                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
389                 glBindTexture( GL_TEXTURE_2D, mTexture );       
390                 glEnable(GL_TEXTURE_2D);
391         }
392 #endif
393 }
394
395 void BL_Texture::SetMapping(int mode)
396 {
397
398         if(!(mode &USEREFL)) {
399                 glDisable(GL_TEXTURE_GEN_S);
400                 glDisable(GL_TEXTURE_GEN_T);
401                 glDisable(GL_TEXTURE_GEN_R);
402                 glDisable(GL_TEXTURE_GEN_Q);
403                 return;
404         }
405
406 #ifdef GL_ARB_texture_cube_map
407         if( mType == GL_TEXTURE_CUBE_MAP_ARB && 
408                 RAS_EXT_support._ARB_texture_cube_map &&
409                 mode &USEREFL) 
410         {
411                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
412                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
413                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
414                 
415                 glEnable(GL_TEXTURE_GEN_S);
416                 glEnable(GL_TEXTURE_GEN_T);
417                 glEnable(GL_TEXTURE_GEN_R);
418                 glDisable(GL_TEXTURE_GEN_Q);
419                 return;
420         }
421         else
422 #endif
423         {
424                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
425                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
426
427                 glEnable(GL_TEXTURE_GEN_S);
428                 glEnable(GL_TEXTURE_GEN_T);
429                 glDisable(GL_TEXTURE_GEN_R);
430                 glDisable(GL_TEXTURE_GEN_Q);
431         }
432 }
433
434
435 void BL_Texture::setTexEnv(BL_Material *mat, bool modulate)
436 {
437 #ifndef GL_ARB_texture_env_combine
438         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
439         return;
440 #else
441         if(modulate || !RAS_EXT_support._ARB_texture_env_combine){
442                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
443                 return;
444         }
445
446         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
447
448         GLfloat blend_operand           = GL_SRC_COLOR;
449         GLfloat blend_operand_prev  = GL_SRC_COLOR;
450         GLfloat alphaOp                         = GL_SRC_ALPHA;
451
452         GLenum combiner = GL_COMBINE_RGB_ARB;
453         GLenum source0  = GL_SOURCE0_RGB_ARB;
454         GLenum source1  = GL_SOURCE1_RGB_ARB;
455         GLenum source2  = GL_SOURCE2_RGB_ARB;
456         GLenum op0              = GL_OPERAND0_RGB_ARB;
457         GLenum op1              = GL_OPERAND1_RGB_ARB;
458         GLenum op2              = GL_OPERAND2_RGB_ARB;
459
460         // switch to alpha combiners
461         if( mat->flag[mUnit]  &TEXALPHA ) {
462                 combiner = GL_COMBINE_ALPHA_ARB;
463                 source0 = GL_SOURCE0_ALPHA_ARB;
464                 source1 = GL_SOURCE1_ALPHA_ARB;
465                 source2 = GL_SOURCE2_ALPHA_ARB;
466                 op0 = GL_OPERAND0_ALPHA_ARB;
467                 op1 = GL_OPERAND1_ALPHA_ARB;
468                 op2 = GL_OPERAND2_ALPHA_ARB;
469                 blend_operand = GL_SRC_ALPHA;
470                 blend_operand_prev = GL_SRC_ALPHA;
471                 // invert
472                 if(mat->flag[mUnit] &TEXNEG) {
473                         blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA;
474                         blend_operand = GL_ONE_MINUS_SRC_ALPHA;
475                 }
476         }
477         else {
478                 if(mat->flag[mUnit] &TEXNEG) {
479                         blend_operand_prev=GL_ONE_MINUS_SRC_COLOR;
480                         blend_operand = GL_ONE_MINUS_SRC_COLOR;
481                 }
482         }
483         bool using_alpha = false;
484
485         if(mat->flag[mUnit]  &USEALPHA){
486                 alphaOp = GL_ONE_MINUS_SRC_ALPHA;
487                 using_alpha=true;
488         }
489         else if(mat->flag[mUnit]  &USENEGALPHA){
490                 alphaOp = GL_SRC_ALPHA;
491                 using_alpha = true;
492         }
493
494         switch( mat->blend_mode[mUnit] ) {
495                 case BLEND_MIX:
496                         {
497                                 // ------------------------------
498                                 if(!using_alpha) {
499                                         GLfloat base_col[4];
500                                         base_col[0]      = base_col[1]  = base_col[2]  = 0.f;
501                                         base_col[3]      = 1.f-mat->color_blend[mUnit];
502                                         glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col );
503                                 }
504                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_INTERPOLATE_ARB);
505                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
506                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
507                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
508                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
509                                 if(!using_alpha)
510                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_CONSTANT_ARB );
511                                 else
512                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_TEXTURE );
513
514                                 glTexEnvf(      GL_TEXTURE_ENV, op2,            alphaOp);
515                         }break;
516                 case BLEND_MUL: 
517                         {
518                                 // ------------------------------
519                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_MODULATE);
520                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
521                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev);
522                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
523                                 if(using_alpha)
524                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
525                                 else
526                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
527                         }break;
528                 case BLEND_ADD: 
529                         {
530                                 // ------------------------------
531                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD_SIGNED_ARB);
532                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
533                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
534                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
535                                 if(using_alpha)
536                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
537                                 else
538                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
539                         }break;
540                 case BLEND_SUB: 
541                         {
542                                 // ------------------------------
543                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_SUBTRACT_ARB);
544                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
545                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
546                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
547                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
548                         }break;
549                 case BLEND_SCR: 
550                         {
551                                 // ------------------------------
552                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD);
553                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
554                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
555                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
556                                 if(using_alpha)
557                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
558                                 else
559                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
560                         } break;
561         }
562         glTexEnvf(      GL_TEXTURE_ENV, GL_RGB_SCALE_ARB,       1.0);
563 #endif //!GL_ARB_texture_env_combine
564 }
565
566 int BL_Texture::GetPow2(int n)
567 {
568         if(!is_pow2(n))
569                 n = smaller_pow2(n);
570
571         return n;
572 }
573
574 extern "C" {
575
576 void my_envmap_split_ima(EnvMap *env)
577 {
578         ImBuf *ibuf;
579         Image *ima;
580         int dx, part;
581         
582         my_free_envmapdata(env);        
583         
584         dx= env->ima->ibuf->y;
585         dx/= 2;
586         if(3*dx != env->ima->ibuf->x) {
587                 printf("Incorrect envmap size\n");
588                 env->ok= 0;
589                 env->ima->ok= 0;
590         }
591         else {
592                 for(part=0; part<6; part++) {
593                         ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0);
594                         ima= (Image*)MEM_callocN(sizeof(Image), "image");
595                         ima->ibuf= ibuf;
596                         ima->ok= 1;
597                         env->cube[part]= ima;
598                 }
599                 IMB_rectcpy(env->cube[0]->ibuf, env->ima->ibuf, 
600                         0, 0, 0, 0, dx, dx);
601                 IMB_rectcpy(env->cube[1]->ibuf, env->ima->ibuf, 
602                         0, 0, dx, 0, dx, dx);
603                 IMB_rectcpy(env->cube[2]->ibuf, env->ima->ibuf, 
604                         0, 0, 2*dx, 0, dx, dx);
605                 IMB_rectcpy(env->cube[3]->ibuf, env->ima->ibuf, 
606                         0, 0, 0, dx, dx, dx);
607                 IMB_rectcpy(env->cube[4]->ibuf, env->ima->ibuf, 
608                         0, 0, dx, dx, dx, dx);
609                 IMB_rectcpy(env->cube[5]->ibuf, env->ima->ibuf, 
610                         0, 0, 2*dx, dx, dx, dx);
611                 env->ok= 2;
612         }
613 }
614
615
616 void my_free_envmapdata(EnvMap *env)
617 {
618         Image *ima;
619         unsigned int a, part;
620         
621         for(part=0; part<6; part++) {
622                 ima= env->cube[part];
623                 if(ima) {
624                         if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
625
626                         for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
627                                 if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
628                         }
629                         MEM_freeN(ima);
630                         env->cube[part]= 0;
631                 }
632         }
633         env->ok= 0;
634 }
635
636
637 } // extern C
638