From 3fcdfbd01ad81639a980cdb552d464090787dc0b Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 2 May 2018 11:38:44 -0400 Subject: [PATCH] Optimized floor rendering --- android/build.gradle | 4 +- .../io/anuke/mindustry/AndroidLauncher.java | 2 +- .../mindustry/content/blocks/Blocks.java | 12 ++-- .../anuke/mindustry/editor/MapRenderer.java | 1 - .../mindustry/graphics/BlockRenderer.java | 2 +- .../{DrawLayer.java => CacheLayer.java} | 2 +- .../mindustry/graphics/FloorRenderer.java | 40 +++++++---- core/src/io/anuke/mindustry/world/Block.java | 6 +- core/src/io/anuke/mindustry/world/Tile.java | 3 - .../mindustry/world/blocks/types/Floor.java | 71 ++++++++++++------- .../world/blocks/types/StaticBlock.java | 4 +- gradle/wrapper/gradle-wrapper.properties | 3 +- 12 files changed, 90 insertions(+), 60 deletions(-) rename core/src/io/anuke/mindustry/graphics/{DrawLayer.java => CacheLayer.java} (98%) diff --git a/android/build.gradle b/android/build.gradle index bc3c955d02..30a58faf35 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -22,8 +22,8 @@ task deploy(type: Copy){ } android { - buildToolsVersion '26.0.2' - compileSdkVersion 26 + buildToolsVersion '27.0.3' + compileSdkVersion 27 sourceSets { main { manifest.srcFile 'AndroidManifest.xml' diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index beb54052be..72a73e5156 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -104,7 +104,7 @@ public class AndroidLauncher extends AndroidApplication{ @Override public boolean isDebug() { - return true; + return false; } @Override diff --git a/core/src/io/anuke/mindustry/content/blocks/Blocks.java b/core/src/io/anuke/mindustry/content/blocks/Blocks.java index 6ce3406b3f..61a1a5d426 100644 --- a/core/src/io/anuke/mindustry/content/blocks/Blocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/Blocks.java @@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.content.StatusEffects; -import io.anuke.mindustry.graphics.DrawLayer; +import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -28,7 +28,7 @@ public class Blocks { space = new Floor("space") {{ variants = 0; - drawLayer = DrawLayer.space; + cacheLayer = CacheLayer.space; solid = true; }}, @@ -46,7 +46,7 @@ public class Blocks { status = StatusEffects.wet; statusIntensity = 1f; drownTime = 140f; - drawLayer = DrawLayer.water; + cacheLayer = CacheLayer.water; }}, water = new Floor("water") {{ @@ -57,7 +57,7 @@ public class Blocks { statusIntensity = 0.9f; liquidDrop = Liquids.water; liquid = true; - drawLayer = DrawLayer.water; + cacheLayer = CacheLayer.water; }}, lava = new Floor("lava") {{ @@ -69,7 +69,7 @@ public class Blocks { variants = 0; liquidDrop = Liquids.lava; liquid = true; - drawLayer = DrawLayer.lava; + cacheLayer = CacheLayer.lava; }}, oil = new Floor("oil") {{ @@ -80,7 +80,7 @@ public class Blocks { variants = 0; liquidDrop = Liquids.oil; liquid = true; - drawLayer = DrawLayer.oil; + cacheLayer = CacheLayer.oil; }}, stone = new Floor("stone") {{ diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index ceef20b7bb..dbc8f87dd5 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -25,7 +25,6 @@ public class MapRenderer { } public void resize(int width, int height){ - //TODO just freezes on tablets if(chunks != null){ for(int x = 0; x < chunks.length; x ++){ for(int y = 0; y < chunks[0].length; y ++){ diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index 130e1d5f19..4c9ad89d37 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -107,7 +107,7 @@ public class BlockRenderer{ Graphics.end(); floorRenderer.beginDraw(); - floorRenderer.drawLayer(DrawLayer.walls); + floorRenderer.drawLayer(CacheLayer.walls); floorRenderer.endDraw(); Graphics.begin(); diff --git a/core/src/io/anuke/mindustry/graphics/DrawLayer.java b/core/src/io/anuke/mindustry/graphics/CacheLayer.java similarity index 98% rename from core/src/io/anuke/mindustry/graphics/DrawLayer.java rename to core/src/io/anuke/mindustry/graphics/CacheLayer.java index cf45bef95f..a9ace6ecc4 100644 --- a/core/src/io/anuke/mindustry/graphics/DrawLayer.java +++ b/core/src/io/anuke/mindustry/graphics/CacheLayer.java @@ -8,7 +8,7 @@ import io.anuke.ucore.graphics.Shader; import static io.anuke.mindustry.Vars.renderer; -public enum DrawLayer { +public enum CacheLayer { water{ @Override public void begin(){ diff --git a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java index b23bbabe83..70a4244585 100644 --- a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java @@ -8,7 +8,7 @@ import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.utils.IntArray; import com.badlogic.gdx.utils.IntSet; import com.badlogic.gdx.utils.IntSet.IntSetIterator; -import com.badlogic.gdx.utils.async.AsyncExecutor; +import com.badlogic.gdx.utils.ObjectSet; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -27,10 +27,8 @@ import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; public class FloorRenderer { - private final static int vsize = 4; - private final static int chunksize = 32; + private final static int chunksize = 64; - private AsyncExecutor executor = new AsyncExecutor(8); private Chunk[][] cache; private CacheBatch cbatch; private IntSet drawnLayerSet = new IntSet(); @@ -59,7 +57,7 @@ public class FloorRenderer { } } - int layers = DrawLayer.values().length; + int layers = CacheLayer.values().length; drawnLayers.clear(); drawnLayerSet.clear(); @@ -95,7 +93,7 @@ public class FloorRenderer { beginDraw(); for(int i = 0; i < drawnLayers.size; i ++) { - DrawLayer layer = DrawLayer.values()[drawnLayers.get(i)]; + CacheLayer layer = CacheLayer.values()[drawnLayers.get(i)]; drawLayer(layer); } @@ -115,7 +113,7 @@ public class FloorRenderer { cbatch.endDraw(); } - public void drawLayer(DrawLayer layer){ + public void drawLayer(CacheLayer layer){ OrthographicCamera camera = Core.camera; int crangex = (int)(camera.viewportWidth * camera.zoom / (chunksize * tilesize))+1; @@ -133,6 +131,7 @@ public class FloorRenderer { } Chunk chunk = cache[worldx][worldy]; + if(chunk.caches[layer.ordinal()] == -1) continue; cbatch.drawCache(chunk.caches[layer.ordinal()]); } } @@ -148,13 +147,28 @@ public class FloorRenderer { private void cacheChunk(int cx, int cy){ Chunk chunk = cache[cx][cy]; + //long time = TimeUtils.nanoTime(); - for(DrawLayer layer : DrawLayer.values()){ + ObjectSet used = new ObjectSet<>(); + + for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++) { + for (int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++) { + Tile tile = world.tile(tilex, tiley); + if (tile != null){ + used.add(tile.block().cacheLayer == CacheLayer.walls ? + CacheLayer.walls : tile.floor().cacheLayer); + } + } + } + + for(CacheLayer layer : used){ cacheChunkLayer(cx, cy, chunk, layer); } + + // Log.info("Time to cache a chunk: {0}", TimeUtils.timeSinceNanos(time) / 1000000f); } - private void cacheChunkLayer(int cx, int cy, Chunk chunk, DrawLayer layer){ + private void cacheChunkLayer(int cx, int cy, Chunk chunk, CacheLayer layer){ Graphics.useBatch(cbatch); cbatch.begin(); @@ -164,13 +178,13 @@ public class FloorRenderer { Tile tile = world.tile(tilex, tiley); if(tile == null) continue; - if(tile.floor().drawLayer == layer && tile.block().drawLayer != DrawLayer.walls){ + if(tile.floor().cacheLayer == layer && tile.block().cacheLayer != CacheLayer.walls){ tile.floor().draw(tile); - }else if(tile.floor().drawLayer.ordinal() < layer.ordinal() && tile.block().drawLayer != DrawLayer.walls && layer != DrawLayer.walls){ + }else if(tile.floor().cacheLayer.ordinal() < layer.ordinal() && tile.block().cacheLayer != CacheLayer.walls && layer != CacheLayer.walls){ tile.floor().drawNonLayer(tile); } - if(tile.block().drawLayer == layer && layer == DrawLayer.walls){ + if(tile.block().cacheLayer == layer && layer == CacheLayer.walls){ Block block = tile.block(); block.draw(tile); } @@ -183,7 +197,7 @@ public class FloorRenderer { } private class Chunk{ - int[] caches = new int[DrawLayer.values().length]; + int[] caches = new int[CacheLayer.values().length]; } public void clearTiles(){ diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 7e59fd139c..08155567b6 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -12,7 +12,7 @@ import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.effect.DamageArea; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.entities.effect.Rubble; -import io.anuke.mindustry.graphics.DrawLayer; +import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; @@ -90,8 +90,8 @@ public class Block extends BaseBlock { public boolean expanded = false; /**Max of timers used.*/ public int timers = 0; - /**Draw layer. Only used for 'cached' rendering.*/ - public DrawLayer drawLayer = DrawLayer.normal; + /**Cache layer. Only used for 'cached' rendering.*/ + public CacheLayer cacheLayer = CacheLayer.normal; /**Layer to draw extra stuff on.*/ public Layer layer = null; /**Extra layer to draw extra extra stuff on.*/ diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 925098c0fd..47c2235435 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -33,9 +33,6 @@ public class Tile implements Position{ /**Tile traversal cost*/ public float cost = 1f; public TileEntity entity; - - public float pathDistance = -1; - public float vecx, vecy; public Tile(int x, int y){ this.x = (short)x; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/Floor.java b/core/src/io/anuke/mindustry/world/blocks/types/Floor.java index 4b5d202430..102b3ad756 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/Floor.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.world.blocks.types; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.content.fx.BlockFx; import io.anuke.mindustry.entities.StatusEffect; @@ -11,13 +12,16 @@ import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.function.Predicate; import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.world; public class Floor extends Block{ - protected TextureRegion tempRegion = new TextureRegion(); - public Predicate blends = block -> block != this; + protected TextureRegion edgeRegion; + protected TextureRegion[] edgeRegions; + protected Vector2[] offsets; + protected Predicate blends = block -> block != this; protected boolean blend = true; public float speedMultiplier = 1f; @@ -35,6 +39,36 @@ public class Floor extends Block{ variants = 3; } + @Override + public void load() { + super.load(); + if(blend) { + edgeRegion = Draw.hasRegion(name + "edge") ? Draw.region(name + "edge") : Draw.region(edge + "edge"); + edgeRegions = new TextureRegion[8]; + offsets = new Vector2[8]; + + for(int i = 0; i < 8; i ++){ + int dx = Geometry.d8[i].x, dy = Geometry.d8[i].y; + + TextureRegion result = new TextureRegion(); + + int sx = -dx*8+2, sy = -dy*8+2; + int x = Mathf.clamp(sx, 0, 12); + int y = Mathf.clamp(sy, 0, 12); + int w = Mathf.clamp(sx+8, 0, 12) - x, h = Mathf.clamp(sy+8, 0, 12) - y; + + float rx = Mathf.clamp(dx*8, 0, 8-w); + float ry = Mathf.clamp(dy*8, 0, 8-h); + + result.setTexture(edgeRegion.getTexture()); + result.setRegion(edgeRegion.getRegionX()+x, edgeRegion.getRegionY()+y+h, w, -h); + + edgeRegions[i] = result; + offsets[i] = new Vector2(-4 + rx, -4 + ry); + } + } + } + @Override public void init(){ super.init(); @@ -63,36 +97,21 @@ public class Floor extends Block{ private void drawEdges(Tile tile, boolean sameLayer){ if(!blend) return; - for(int dx = -1; dx <= 1; dx ++){ - for(int dy = -1; dy <= 1; dy ++){ + for(int i = 0; i < 8; i ++){ + int dx = Geometry.d8[i].x, dy = Geometry.d8[i].y; - if(dx == 0 && dy == 0) continue; + Tile other = world.tile(tile.x+dx, tile.y+dy); - Tile other = world.tile(tile.x+dx, tile.y+dy); + if(other == null) continue; - if(other == null) continue; + Floor floor = other.floor(); - Block floor = other.floor(); + if(floor.id <= this.id || !blends.test(floor) || (floor.cacheLayer.ordinal() > this.cacheLayer.ordinal() && !sameLayer) || + (sameLayer && floor.cacheLayer == this.cacheLayer)) continue; - if(floor.id <= this.id || !blends.test(floor) || (floor.drawLayer.ordinal() > this.drawLayer.ordinal() && !sameLayer) || - (sameLayer && floor.drawLayer == this.drawLayer)) continue; + TextureRegion region = floor.edgeRegions[i]; - TextureRegion region = Draw.hasRegion(floor.name() + "edge") ? Draw.region(floor.name() + "edge") : - Draw.region(floor.edge + "edge"); - - int sx = -dx*8+2, sy = -dy*8+2; - int x = Mathf.clamp(sx, 0, 12); - int y = Mathf.clamp(sy, 0, 12); - int w = Mathf.clamp(sx+8, 0, 12) - x, h = Mathf.clamp(sy+8, 0, 12) - y; - - float rx = Mathf.clamp(dx*8, 0, 8-w); - float ry = Mathf.clamp(dy*8, 0, 8-h); - - tempRegion.setTexture(region.getTexture()); - tempRegion.setRegion(region.getRegionX()+x, region.getRegionY()+y+h, w, -h); - - Draw.crect(tempRegion, tile.worldx()-4 + rx, tile.worldy()-4 + ry, w, h); - } + Draw.crect(region, tile.worldx() + floor.offsets[i].x, tile.worldy() + floor.offsets[i].y, region.getRegionWidth(), region.getRegionHeight()); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/StaticBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/StaticBlock.java index ccc43cc0dc..dca911701d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/StaticBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/StaticBlock.java @@ -1,13 +1,13 @@ package io.anuke.mindustry.world.blocks.types; -import io.anuke.mindustry.graphics.DrawLayer; +import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.world.Block; public class StaticBlock extends Block{ public StaticBlock(String name) { super(name); - drawLayer = DrawLayer.walls; + cacheLayer = CacheLayer.walls; } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index be280bec02..e956872e4b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Wed May 02 11:26:02 EDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip