1 2 package com.badlogic.gdx.graphics.glutils; 3 4 import com.badlogic.gdx.Gdx; 5 import com.badlogic.gdx.files.FileHandle; 6 import com.badlogic.gdx.graphics.Cubemap; 7 import com.badlogic.gdx.graphics.Cubemap.CubemapSide; 8 import com.badlogic.gdx.graphics.CubemapData; 9 import com.badlogic.gdx.graphics.GL20; 10 import com.badlogic.gdx.graphics.GLTexture; 11 import com.badlogic.gdx.graphics.Pixmap; 12 import com.badlogic.gdx.graphics.Pixmap.Blending; 13 import com.badlogic.gdx.graphics.Pixmap.Format; 14 import com.badlogic.gdx.graphics.Texture; 15 import com.badlogic.gdx.graphics.TextureData; 16 import com.badlogic.gdx.utils.GdxRuntimeException; 17 18 /** A FacedCubemapData holds a cubemap data definition based on a {@link TextureData} per face. 19 * 20 * @author Vincent Nousquet */ 21 public class FacedCubemapData implements CubemapData { 22 23 protected final TextureData[] data = new TextureData[6]; 24 25 /** Construct an empty Cubemap. Use the load(...) methods to set the texture of each side. Every side of the cubemap must be set 26 * before it can be used. */ 27 public FacedCubemapData () { 28 this((TextureData)null, (TextureData)null, (TextureData)null, (TextureData)null, (TextureData)null, (TextureData)null); 29 } 30 31 /** Construct a Cubemap with the specified texture files for the sides, optionally generating mipmaps. */ 32 public FacedCubemapData (FileHandle positiveX, FileHandle negativeX, FileHandle positiveY, FileHandle negativeY, 33 FileHandle positiveZ, FileHandle negativeZ) { 34 this(TextureData.Factory.loadFromFile(positiveX, false), TextureData.Factory.loadFromFile(negativeX, 35 false), TextureData.Factory.loadFromFile(positiveY, false), TextureData.Factory.loadFromFile( 36 negativeY, false), TextureData.Factory.loadFromFile(positiveZ, false), TextureData.Factory 37 .loadFromFile(negativeZ, false)); 38 } 39 40 /** Construct a Cubemap with the specified texture files for the sides, optionally generating mipmaps. */ 41 public FacedCubemapData (FileHandle positiveX, FileHandle negativeX, FileHandle positiveY, FileHandle negativeY, 42 FileHandle positiveZ, FileHandle negativeZ, boolean useMipMaps) { 43 this(TextureData.Factory.loadFromFile(positiveX, useMipMaps), TextureData.Factory.loadFromFile( 44 negativeX, useMipMaps), TextureData.Factory.loadFromFile(positiveY, useMipMaps), TextureData.Factory 45 .loadFromFile(negativeY, useMipMaps), TextureData.Factory.loadFromFile(positiveZ, useMipMaps), 46 TextureData.Factory.loadFromFile(negativeZ, useMipMaps)); 47 } 48 49 /** Construct a Cubemap with the specified {@link Pixmap}s for the sides, does not generate mipmaps. */ 50 public FacedCubemapData (Pixmap positiveX, Pixmap negativeX, Pixmap positiveY, Pixmap negativeY, Pixmap positiveZ, 51 Pixmap negativeZ) { 52 this(positiveX, negativeX, positiveY, negativeY, positiveZ, negativeZ, false); 53 } 54 55 /** Construct a Cubemap with the specified {@link Pixmap}s for the sides, optionally generating mipmaps. */ 56 public FacedCubemapData (Pixmap positiveX, Pixmap negativeX, Pixmap positiveY, Pixmap negativeY, Pixmap positiveZ, 57 Pixmap negativeZ, boolean useMipMaps) { 58 this(positiveX == null ? null : new PixmapTextureData(positiveX, null, useMipMaps, false), negativeX == null ? null 59 : new PixmapTextureData(negativeX, null, useMipMaps, false), positiveY == null ? null : new PixmapTextureData(positiveY, 60 null, useMipMaps, false), negativeY == null ? null : new PixmapTextureData(negativeY, null, useMipMaps, false), 61 positiveZ == null ? null : new PixmapTextureData(positiveZ, null, useMipMaps, false), negativeZ == null ? null 62 : new PixmapTextureData(negativeZ, null, useMipMaps, false)); 63 } 64 65 /** Construct a Cubemap with {@link Pixmap}s for each side of the specified size. */ 66 public FacedCubemapData (int width, int height, int depth, Format format) { 67 this(new PixmapTextureData(new Pixmap(depth, height, format), null, false, true), new PixmapTextureData(new Pixmap(depth, 68 height, format), null, false, true), new PixmapTextureData(new Pixmap(width, depth, format), null, false, true), 69 new PixmapTextureData(new Pixmap(width, depth, format), null, false, true), new PixmapTextureData(new Pixmap(width, 70 height, format), null, false, true), new PixmapTextureData(new Pixmap(width, height, format), null, false, true)); 71 } 72 73 /** Construct a Cubemap with the specified {@link TextureData}'s for the sides */ 74 public FacedCubemapData (TextureData positiveX, TextureData negativeX, TextureData positiveY, TextureData negativeY, 75 TextureData positiveZ, TextureData negativeZ) { 76 data[0] = positiveX; 77 data[1] = negativeX; 78 data[2] = positiveY; 79 data[3] = negativeY; 80 data[4] = positiveZ; 81 data[5] = negativeZ; 82 } 83 84 @Override 85 public boolean isManaged () { 86 for (TextureData data : this.data) 87 if (!data.isManaged()) return false; 88 return true; 89 } 90 91 /** Loads the texture specified using the {@link FileHandle} and sets it to specified side, overwriting any previous data set to 92 * that side. Note that you need to reload through {@link Cubemap#load(CubemapData)} any cubemap using this data for the change 93 * to be taken in account. 94 * @param side The {@link CubemapSide} 95 * @param file The texture {@link FileHandle} */ 96 public void load (CubemapSide side, FileHandle file) { 97 data[side.index] = TextureData.Factory.loadFromFile(file, false); 98 } 99 100 /** Sets the specified side of this cubemap to the specified {@link Pixmap}, overwriting any previous data set to that side. 101 * Note that you need to reload through {@link Cubemap#load(CubemapData)} any cubemap using this data for the change to be 102 * taken in account. 103 * @param side The {@link CubemapSide} 104 * @param pixmap The {@link Pixmap} */ 105 public void load (CubemapSide side, Pixmap pixmap) { 106 data[side.index] = pixmap == null ? null : new PixmapTextureData(pixmap, null, false, false); 107 } 108 109 /** @return True if all sides of this cubemap are set, false otherwise. */ 110 public boolean isComplete () { 111 for (int i = 0; i < data.length; i++) 112 if (data[i] == null) return false; 113 return true; 114 } 115 116 /** @return The {@link TextureData} for the specified side, can be null if the cubemap is incomplete. */ 117 public TextureData getTextureData (CubemapSide side) { 118 return data[side.index]; 119 } 120 121 @Override 122 public int getWidth () { 123 int tmp, width = 0; 124 if (data[CubemapSide.PositiveZ.index] != null && (tmp = data[CubemapSide.PositiveZ.index].getWidth()) > width) width = tmp; 125 if (data[CubemapSide.NegativeZ.index] != null && (tmp = data[CubemapSide.NegativeZ.index].getWidth()) > width) width = tmp; 126 if (data[CubemapSide.PositiveY.index] != null && (tmp = data[CubemapSide.PositiveY.index].getWidth()) > width) width = tmp; 127 if (data[CubemapSide.NegativeY.index] != null && (tmp = data[CubemapSide.NegativeY.index].getWidth()) > width) width = tmp; 128 return width; 129 } 130 131 @Override 132 public int getHeight () { 133 int tmp, height = 0; 134 if (data[CubemapSide.PositiveZ.index] != null && (tmp = data[CubemapSide.PositiveZ.index].getHeight()) > height) 135 height = tmp; 136 if (data[CubemapSide.NegativeZ.index] != null && (tmp = data[CubemapSide.NegativeZ.index].getHeight()) > height) 137 height = tmp; 138 if (data[CubemapSide.PositiveX.index] != null && (tmp = data[CubemapSide.PositiveX.index].getHeight()) > height) 139 height = tmp; 140 if (data[CubemapSide.NegativeX.index] != null && (tmp = data[CubemapSide.NegativeX.index].getHeight()) > height) 141 height = tmp; 142 return height; 143 } 144 145 @Override 146 public boolean isPrepared () { 147 return false; 148 } 149 150 @Override 151 public void prepare () { 152 if (!isComplete()) throw new GdxRuntimeException("You need to complete your cubemap data before using it"); 153 for (int i = 0; i < data.length; i++) 154 if (!data[i].isPrepared()) data[i].prepare(); 155 } 156 157 @Override 158 public void consumeCubemapData () { 159 for (int i = 0; i < data.length; i++) { 160 if (data[i].getType() == TextureData.TextureDataType.Custom) { 161 data[i].consumeCustomData(GL20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); 162 } else { 163 Pixmap pixmap = data[i].consumePixmap(); 164 boolean disposePixmap = data[i].disposePixmap(); 165 if (data[i].getFormat() != pixmap.getFormat()) { 166 Pixmap tmp = new Pixmap(pixmap.getWidth(), pixmap.getHeight(), data[i].getFormat()); 167 Blending blend = Pixmap.getBlending(); 168 Pixmap.setBlending(Blending.None); 169 tmp.drawPixmap(pixmap, 0, 0, 0, 0, pixmap.getWidth(), pixmap.getHeight()); 170 Pixmap.setBlending(blend); 171 if (data[i].disposePixmap()) pixmap.dispose(); 172 pixmap = tmp; 173 disposePixmap = true; 174 } 175 Gdx.gl.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 1); 176 Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), 177 pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); 178 } 179 } 180 } 181 182 } 183