+//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
+typedef struct suffixinfo_s
+{
+ char *suffix;
+ qboolean flipx, flipy, flipdiagonal;
+}
+suffixinfo_t;
+static suffixinfo_t suffix[3][6] =
+{
+ {
+ {"px", false, false, false},
+ {"nx", false, false, false},
+ {"py", false, false, false},
+ {"ny", false, false, false},
+ {"pz", false, false, false},
+ {"nz", false, false, false}
+ },
+ {
+ {"posx", false, false, false},
+ {"negx", false, false, false},
+ {"posy", false, false, false},
+ {"negy", false, false, false},
+ {"posz", false, false, false},
+ {"negz", false, false, false}
+ },
+ {
+ {"rt", true, false, true},
+ {"lf", false, true, true},
+ {"ft", true, true, false},
+ {"bk", false, false, false},
+ {"up", true, false, true},
+ {"dn", true, false, true}
+ }
+};
+
+static int componentorder[4] = {0, 1, 2, 3};
+
+rtexture_t *R_LoadCubemap(const char *basename)
+{
+ int i, j, cubemapsize;
+ unsigned char *cubemappixels, *image_buffer;
+ rtexture_t *cubemaptexture;
+ char name[256];
+ // must start 0 so the first loadimagepixels has no requested width/height
+ cubemapsize = 0;
+ cubemappixels = NULL;
+ cubemaptexture = NULL;
+ // keep trying different suffix groups (posx, px, rt) until one loads
+ for (j = 0;j < 3 && !cubemappixels;j++)
+ {
+ // load the 6 images in the suffix group
+ for (i = 0;i < 6;i++)
+ {
+ // generate an image name based on the base and and suffix
+ dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
+ // load it
+ if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
+ {
+ // an image loaded, make sure width and height are equal
+ if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
+ {
+ // if this is the first image to load successfully, allocate the cubemap memory
+ if (!cubemappixels && image_width >= 1)
+ {
+ cubemapsize = image_width;
+ // note this clears to black, so unavailable sides are black
+ cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
+ }
+ // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
+ if (cubemappixels)
+ Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
+ }
+ else
+ Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
+ // free the image
+ Mem_Free(image_buffer);
+ }
+ }
+ }
+ // if a cubemap loaded, upload it
+ if (cubemappixels)
+ {
+ if (developer_loading.integer)
+ Con_Printf("loading cubemap \"%s\"\n", basename);
+
+ cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
+ Mem_Free(cubemappixels);
+ }
+ else
+ {
+ Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
+ if (developer_loading.integer)
+ {
+ Con_Printf("(tried tried images ");
+ for (j = 0;j < 3;j++)
+ for (i = 0;i < 6;i++)
+ Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
+ Con_Print(" and was unable to find any of them).\n");
+ }
+ }
+ return cubemaptexture;
+}
+
+rtexture_t *R_GetCubemap(const char *basename)
+{
+ int i;
+ for (i = 0;i < r_texture_numcubemaps;i++)
+ if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
+ return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
+ if (i >= MAX_CUBEMAPS)
+ return r_texture_whitecube;
+ r_texture_numcubemaps++;
+ strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
+ r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
+ return r_texture_cubemaps[i].texture;
+}
+
+void R_FreeCubemaps(void)
+{
+ int i;
+ for (i = 0;i < r_texture_numcubemaps;i++)
+ {
+ if (developer_loading.integer)
+ Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
+ if (r_texture_cubemaps[i].texture)
+ R_FreeTexture(r_texture_cubemaps[i].texture);
+ }
+ r_texture_numcubemaps = 0;
+}
+