package openmods.renderer; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import java.util.List; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.util.ResourceLocation; import openmods.utils.ByteUtils; public class DynamicTextureAtlas { public class AtlasCell { private int[] pixels; public void setPixels(int[] pixels) { this.pixels = pixels; } public float minU; public float minV; public float maxU; public float maxV; } private final List<AtlasCell> cells = Lists.newArrayList(); public final int cellSize; private final TextureManager manager; private final DisposableDynamicTexture textureWrapper; private final ResourceLocation textureLocation; public DynamicTextureAtlas(TextureManager manager, int cellSize) { Preconditions.checkArgument(ByteUtils.isPowerOfTwo(cellSize), "NO POWER!"); this.manager = manager; this.cellSize = cellSize; this.textureWrapper = new DisposableDynamicTexture(); this.textureLocation = textureWrapper.register(manager, "dyn-atlas"); } public void bind() { manager.bindTexture(textureLocation); } public AtlasCell allocateCell() { AtlasCell cell = new AtlasCell(); cells.add(cell); return cell; } public void clearCells() { cells.clear(); } public void compile() { int count = cells.size(); Preconditions.checkState(count > 0, "No cells added"); int side = (int)Math.ceil(Math.sqrt(count)); int width = ByteUtils.nextPowerOf2(side); int area = width * width; int height = (count <= area / 2)? width / 2 : width; textureWrapper.resize(width * cellSize, height * cellSize); int[] buffer = textureWrapper.allocate(); final int pixelsPerLine = width * cellSize; final int pixelsPerCellRow = pixelsPerLine * cellSize; final float cellU = 1.0f / width; final float cellV = 1.0f / height; for (int cell = 0; cell < count; cell++) { int cellX = cell % width; int cellY = cell / width; AtlasCell cellData = cells.get(cell); int cellStart = cellY * pixelsPerCellRow + cellX * cellSize; for (int row = 0; row < cellSize; row++) { int dstPos = cellStart + row * pixelsPerLine; int srcPos = row * cellSize; System.arraycopy(cellData.pixels, srcPos, buffer, dstPos, 64); } cellData.pixels = null; cellData.minU = (float)cellX / width; cellData.minV = (float)cellY / height; cellData.maxU = cellData.minU + cellU; cellData.maxV = cellData.minV + cellV; } textureWrapper.updateAndDeallocate(); } }