diff --git a/core/src/mindustry/graphics/g3d/MeshBuilder.java b/core/src/mindustry/graphics/g3d/MeshBuilder.java index 64d9ef8ec6..af2a7e040f 100644 --- a/core/src/mindustry/graphics/g3d/MeshBuilder.java +++ b/core/src/mindustry/graphics/g3d/MeshBuilder.java @@ -29,6 +29,27 @@ public class MeshBuilder{ return buildIcosphere(divisions, radius, Color.white); } + public static Mesh buildPlanetGrid(PlanetGrid grid, Color color, float scale){ + int total = 0; + for(Ptile tile : grid.tiles){ + total += tile.corners.length * 2; + } + + begin(total * (3 + 3 + 1)); + for(Ptile tile : grid.tiles){ + Corner[] c = tile.corners; + for(int i = 0; i < c.length; i++){ + Vec3 a = v1.set(c[i].v).scl(scale); + Vec3 b = v2.set(c[(i + 1) % c.length].v).scl(scale); + + vert(a, Vec3.Z, color); + vert(b, Vec3.Z, color); + } + } + + return end(); + } + public static Mesh buildHex(Color color, int divisions, boolean lines, float radius){ return buildHex(new HexMesher(){ @Override diff --git a/core/src/mindustry/graphics/g3d/PlanetRenderer.java b/core/src/mindustry/graphics/g3d/PlanetRenderer.java index 1af20f68ed..80f95767c7 100644 --- a/core/src/mindustry/graphics/g3d/PlanetRenderer.java +++ b/core/src/mindustry/graphics/g3d/PlanetRenderer.java @@ -22,14 +22,11 @@ public class PlanetRenderer implements Disposable{ borderColor = Pal.accent.cpy().a(0.3f), shadowColor = new Color(0, 0, 0, 0.7f); - private static final Seq points = new Seq<>(); - /** Camera used for rendering. */ public final Camera3D cam = new Camera3D(); /** Raw vertex batch. */ public final VertexBatch3D batch = new VertexBatch3D(20000, false, true, 0); - private final Mesh[] outlines = new Mesh[10]; public final PlaneBatch3D projector = new PlaneBatch3D(); public final Mat3D mat = new Mat3D(); public final FrameBuffer buffer = new FrameBuffer(2, 2, true); @@ -179,26 +176,7 @@ public class PlanetRenderer implements Disposable{ public void renderSectors(Planet planet, PlanetParams params){ if(params.uiAlpha <= 0.02f) return; - - //apply transformed position - batch.proj().mul(planet.getTransform(mat)); - - if(params.renderer != null){ - params.renderer.renderSectors(planet); - } - - //render sector grid - float scaledOutlineRad = outlineRad * planet.radius; - Mesh mesh = outline(planet.grid.size, planet.radius); - Shader shader = Shaders.planetGrid; - Vec3 tile = planet.intersect(cam.getMouseRay(), scaledOutlineRad); - Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile.sub(planet.position).rotate(Vec3.Y, planet.getRotation()), 0.2f); - - shader.bind(); - shader.setUniformMatrix4("u_proj", cam.combined.val); - shader.setUniformMatrix4("u_trans", planet.getTransform(mat).val); - shader.apply(); - mesh.render(shader, Gl.lines); + planet.renderSectors(batch, cam, params); } public void drawArc(Planet planet, Vec3 a, Vec3 b){ @@ -210,48 +188,11 @@ public class PlanetRenderer implements Disposable{ } public void drawArc(Planet planet, Vec3 a, Vec3 b, Color from, Color to, float length, float timeScale, int pointCount){ - //increase curve height when on opposite side of planet, so it doesn't tunnel through - float scaledOutlineRad = outlineRad * planet.radius; - float dot = 1f - (Tmp.v32.set(a).nor().dot(Tmp.v33.set(b).nor()) + 1f)/2f; - - Vec3 avg = Tmp.v31.set(b).add(a).scl(0.5f); - avg.setLength(planet.radius*(1f+length) + dot * 1.35f); - - points.clear(); - points.addAll(Tmp.v33.set(b).setLength(scaledOutlineRad), Tmp.v31, Tmp.v34.set(a).setLength(scaledOutlineRad)); - Tmp.bz3.set(points); - - for(int i = 0; i < pointCount + 1; i++){ - float f = i / (float)pointCount; - Tmp.c1.set(from).lerp(to, (f+ Time.globalTime /timeScale)%1f); - batch.color(Tmp.c1); - batch.vertex(Tmp.bz3.valueAt(Tmp.v32, f)); - } - batch.flush(Gl.lineStrip); + planet.drawArc(batch, a, b, from, to, length, timeScale, pointCount); } public void drawBorders(Sector sector, Color base, float alpha){ - Color color = Tmp.c1.set(base).a((base.a + 0.3f + Mathf.absin(Time.globalTime, 5f, 0.3f)) * alpha); - - float r1 = 1f * sector.planet.radius; - float r2 = outlineRad * sector.planet.radius + 0.001f; - - for(int i = 0; i < sector.tile.corners.length; i++){ - Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; - - Tmp.v31.set(c.v).setLength(r2); - Tmp.v32.set(next.v).setLength(r2); - Tmp.v33.set(c.v).setLength(r1); - - batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); - - Tmp.v31.set(next.v).setLength(r2); - Tmp.v32.set(next.v).setLength(r1); - Tmp.v33.set(c.v).setLength(r1); - - batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); - } - + sector.planet.drawBorders(batch, sector, base, alpha); if(batch.getNumVertices() >= batch.getMaxVertices() - 6 * 6){ batch.flush(Gl.triangles); } @@ -279,11 +220,7 @@ public class PlanetRenderer implements Disposable{ } public void fill(Sector sector, Color color, float offset){ - float rr = outlineRad * sector.planet.radius + offset; - for(int i = 0; i < sector.tile.corners.length; i++){ - Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; - batch.tri(Tmp.v31.set(c.v).setLength(rr), Tmp.v32.set(next.v).setLength(rr), Tmp.v33.set(sector.tile.v).setLength(rr), color); - } + sector.planet.fill(batch, sector, color, offset); } public void drawSelection(Sector sector, float alpha){ @@ -291,43 +228,7 @@ public class PlanetRenderer implements Disposable{ } public void drawSelection(Sector sector, Color color, float stroke, float length){ - float arad = (outlineRad + length) * sector.planet.radius; - - for(int i = 0; i < sector.tile.corners.length; i++){ - Corner next = sector.tile.corners[(i + 1) % sector.tile.corners.length]; - Corner curr = sector.tile.corners[i]; - - next.v.scl(arad); - curr.v.scl(arad); - sector.tile.v.scl(arad); - - Tmp.v31.set(curr.v).sub(sector.tile.v).setLength(curr.v.dst(sector.tile.v) - stroke).add(sector.tile.v); - Tmp.v32.set(next.v).sub(sector.tile.v).setLength(next.v.dst(sector.tile.v) - stroke).add(sector.tile.v); - - batch.tri(curr.v, next.v, Tmp.v31, color); - batch.tri(Tmp.v31, next.v, Tmp.v32, color); - - sector.tile.v.scl(1f / arad); - next.v.scl(1f / arad); - curr.v.scl(1f /arad); - } - } - - public Mesh outline(int size, float radiusScale){ - if(outlines[size] == null){ - outlines[size] = MeshBuilder.buildHex(new HexMesher(){ - @Override - public float getHeight(Vec3 position){ - return 0; - } - - @Override - public Color getColor(Vec3 position){ - return outlineColor; - } - }, size, true, outlineRad * radiusScale, 0.2f); - } - return outlines[size]; + sector.planet.drawSelection(batch, sector, color, stroke, length); } @Override @@ -338,11 +239,6 @@ public class PlanetRenderer implements Disposable{ atmosphere.dispose(); buffer.dispose(); bloom.dispose(); - for(Mesh m : outlines){ - if(m != null){ - m.dispose(); - } - } } public interface PlanetInterfaceRenderer{ diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index ee7a9bcd42..e63db3a4e8 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -4,6 +4,7 @@ import arc.*; import arc.func.*; import arc.graphics.*; import arc.graphics.g3d.*; +import arc.graphics.gl.*; import arc.math.*; import arc.math.geom.*; import arc.struct.*; @@ -23,14 +24,22 @@ import mindustry.world.blocks.*; import mindustry.world.meta.*; import static mindustry.Vars.*; +import static mindustry.graphics.g3d.PlanetRenderer.*; public class Planet extends UnlockableContent{ /** intersect() temp var. */ private static final Vec3 intersectResult = new Vec3(); + /** drawSectors() temp matrix. */ + private static final Mat3D mat = new Mat3D(); + /** drawArc() temp curve points. */ + private static final Seq points = new Seq<>(); + /** Mesh used for rendering. Created on load() - will be null on the server! */ public @Nullable GenericMesh mesh; /** Mesh used for rendering planet clouds. Null if no clouds are present. */ public @Nullable GenericMesh cloudMesh; + /** Mesh used for rendering planet grid outlines. Null on server or if {@link #grid} is null. */ + public @Nullable Mesh gridMesh; /** Position in global coordinates. Will be 0,0,0 until the Universe updates it. */ public Vec3 position = new Vec3(); /** Grid used for the sectors on the planet. Null if this planet can't be landed on. */ @@ -141,6 +150,8 @@ public class Planet extends UnlockableContent{ public Seq unlockedOnLand = new Seq<>(); /** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */ public Prov meshLoader = () -> new ShaderSphereMesh(this, Shaders.unlit, 2), cloudMeshLoader = () -> null; + /** Loads the planet grid outline mesh. Clientside only. */ + public Prov gridMeshLoader = () -> MeshBuilder.buildPlanetGrid(grid, outlineColor, outlineRad * radius); public Planet(String name, Planet parent, float radius){ super(name); @@ -312,12 +323,12 @@ public class Planet extends UnlockableContent{ if(!headless){ mesh = meshLoader.get(); cloudMesh = cloudMeshLoader.get(); + if(grid != null) gridMesh = gridMeshLoader.get(); } } @Override public void init(){ - if(techTree == null){ techTree = TechTree.roots.find(n -> n.planet == this); } @@ -418,4 +429,106 @@ public class Planet extends UnlockableContent{ cloudMesh.render(params, projection, transform); } } + + /** Draws sector borders. Supply the batch with {@link Gl#triangles triangle} vertices. */ + public void drawBorders(VertexBatch3D batch, Sector sector, Color base, float alpha){ + Color color = Tmp.c1.set(base).a((base.a + 0.3f + Mathf.absin(Time.globalTime, 5f, 0.3f)) * alpha); + + float r1 = radius; + float r2 = outlineRad * radius + 0.001f; + + for(int i = 0; i < sector.tile.corners.length; i++){ + Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; + + Tmp.v31.set(c.v).setLength(r2); + Tmp.v32.set(next.v).setLength(r2); + Tmp.v33.set(c.v).setLength(r1); + + batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); + + Tmp.v31.set(next.v).setLength(r2); + Tmp.v32.set(next.v).setLength(r1); + Tmp.v33.set(c.v).setLength(r1); + + batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); + } + } + + /** Draws sector plane. Supply the batch with {@link Gl#triangles triangle} vertices. */ + public void fill(VertexBatch3D batch, Sector sector, Color color, float offset){ + float rr = outlineRad * radius + offset; + for(int i = 0; i < sector.tile.corners.length; i++){ + Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; + batch.tri(Tmp.v31.set(c.v).setLength(rr), Tmp.v32.set(next.v).setLength(rr), Tmp.v33.set(sector.tile.v).setLength(rr), color); + } + } + + /** Draws sector when selected. Supply the batch with {@link Gl#triangles triangle} vertices. */ + public void drawSelection(VertexBatch3D batch, Sector sector, Color color, float stroke, float length){ + float arad = (outlineRad + length) * radius; + + for(int i = 0; i < sector.tile.corners.length; i++){ + Corner next = sector.tile.corners[(i + 1) % sector.tile.corners.length]; + Corner curr = sector.tile.corners[i]; + + next.v.scl(arad); + curr.v.scl(arad); + sector.tile.v.scl(arad); + + Tmp.v31.set(curr.v).sub(sector.tile.v).setLength(curr.v.dst(sector.tile.v) - stroke).add(sector.tile.v); + Tmp.v32.set(next.v).sub(sector.tile.v).setLength(next.v.dst(sector.tile.v) - stroke).add(sector.tile.v); + + batch.tri(curr.v, next.v, Tmp.v31, color); + batch.tri(Tmp.v31, next.v, Tmp.v32, color); + + sector.tile.v.scl(1f / arad); + next.v.scl(1f / arad); + curr.v.scl(1f /arad); + } + } + + /** Renders sector outlines. */ + public void renderSectors(VertexBatch3D batch, Camera3D cam, PlanetParams params){ + //apply transformed position + batch.proj().mul(getTransform(mat)); + + if(params.renderer != null){ + params.renderer.renderSectors(this); + } + + //render sector grid + float scaledOutlineRad = outlineRad * radius; + Mesh mesh = gridMesh; + Shader shader = Shaders.planetGrid; + Vec3 tile = intersect(cam.getMouseRay(), scaledOutlineRad); + Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile.sub(position).rotate(Vec3.Y, getRotation()), 0.2f); + + shader.bind(); + shader.setUniformMatrix4("u_proj", cam.combined.val); + shader.setUniformMatrix4("u_trans", getTransform(mat).val); + shader.apply(); + mesh.render(shader, Gl.lines); + } + + /** Draws an arc from one point to another on the planet. */ + public void drawArc(VertexBatch3D batch, Vec3 a, Vec3 b, Color from, Color to, float length, float timeScale, int pointCount){ + //increase curve height when on opposite side of planet, so it doesn't tunnel through + float scaledOutlineRad = outlineRad * radius; + float dot = 1f - (Tmp.v32.set(a).nor().dot(Tmp.v33.set(b).nor()) + 1f)/2f; + + Vec3 avg = Tmp.v31.set(b).add(a).scl(0.5f); + avg.setLength(radius * (1f + length) + dot * 1.35f); + + points.clear(); + points.addAll(Tmp.v33.set(b).setLength(scaledOutlineRad), Tmp.v31, Tmp.v34.set(a).setLength(scaledOutlineRad)); + Tmp.bz3.set(points); + + for(int i = 0; i < pointCount + 1; i++){ + float f = i / (float)pointCount; + Tmp.c1.set(from).lerp(to, (f + Time.globalTime / timeScale) % 1f); + batch.color(Tmp.c1); + batch.vertex(Tmp.bz3.valueAt(Tmp.v32, f)); + } + batch.flush(Gl.lineStrip); + } } diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 3ab79fb947..c26e3f9f2c 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -150,11 +150,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ @Override public void zoom(InputEvent event, float initialDistance, float distance){ - if(lastZoom < 0){ - lastZoom = zoom; - } + if(lastZoom < 0){ + lastZoom = zoom; + } - zoom = (Mathf.clamp(initialDistance / distance * lastZoom, state.planet.minZoom, 2f)); + zoom = (Mathf.clamp(initialDistance / distance * lastZoom, state.planet.minZoom, 2f)); } @Override