mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-01-10 07:07:03 +07:00
Real-time lighting + solar system rendering
This commit is contained in:
parent
f0857fa22d
commit
7a01719816
@ -2,20 +2,22 @@ attribute vec4 a_position;
|
||||
attribute vec3 a_normal;
|
||||
attribute vec4 a_color;
|
||||
|
||||
uniform mat4 u_projModelView;
|
||||
uniform mat4 u_proj;
|
||||
uniform mat4 u_trans;
|
||||
uniform vec3 u_lightdir;
|
||||
uniform vec3 u_ambientColor;
|
||||
|
||||
varying vec4 v_col;
|
||||
|
||||
const vec3 ambientColor = vec3(1.0);
|
||||
const vec3 ambientDir = normalize(vec3(1.0, 1.0, 1.0));
|
||||
const vec3 diffuse = vec3(0.3);
|
||||
const vec3 diffuse = vec3(0.2);
|
||||
const vec3 v1 = vec3(1.0, 0.0, 1.0);
|
||||
const vec3 v2 = vec3(1.0, 0.5, 0.0);
|
||||
|
||||
void main(){
|
||||
vec3 norc = ambientColor * (diffuse + vec3(clamp((dot(a_normal, u_lightdir) + 1.0) / 2.0, 0.0, 1.0)));
|
||||
vec3 norc = u_ambientColor * (diffuse + vec3(clamp((dot(a_normal, u_lightdir) + 1.0) / 2.0, 0.0, 1.0)));
|
||||
|
||||
v_col = a_color * vec4(norc, 1.0);
|
||||
gl_Position = u_projModelView * a_position;
|
||||
gl_Position = u_proj * u_trans * a_position;
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
attribute vec4 a_position;
|
||||
attribute vec4 a_color;
|
||||
|
||||
uniform mat4 u_projModelView;
|
||||
uniform mat4 u_proj;
|
||||
uniform mat4 u_trans;
|
||||
|
||||
varying vec4 v_col;
|
||||
varying vec4 v_position;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projModelView * a_position;
|
||||
gl_Position = u_proj * u_trans * a_position;
|
||||
v_col = a_color;
|
||||
v_position = a_position;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
attribute vec4 a_position;
|
||||
attribute vec3 a_normal;
|
||||
|
||||
uniform mat4 u_projModelView;
|
||||
uniform mat4 u_proj;
|
||||
uniform mat4 u_trans;
|
||||
|
||||
uniform vec3 u_center;
|
||||
uniform float u_time;
|
||||
uniform int u_octaves;
|
||||
uniform float u_falloff;
|
||||
@ -100,8 +100,7 @@ float onoise(vec4 pos, int octaves, float falloff, float scl, float po){
|
||||
}
|
||||
|
||||
void main(){
|
||||
vec3 center = u_center;
|
||||
vec4 pos = u_projModelView * (a_position);
|
||||
vec4 pos = a_position;
|
||||
|
||||
float height = onoise(vec4(a_position.xyz, u_time + u_seed), u_octaves, u_falloff, u_scale, u_power);
|
||||
|
||||
@ -111,7 +110,5 @@ void main(){
|
||||
|
||||
v_height = (height + (onoise(vec4(a_position.xyz, u_time + u_seed*2.0), u_octaves, u_falloff, u_scale, u_power) - 0.5) / 6.0 - 0.5) * u_spread + 0.5;
|
||||
|
||||
vec3 rel = (-vec3(pos) + ((vec3(pos) - center) * dst + center));
|
||||
|
||||
gl_Position = u_projModelView * (a_position + vec4(center.xyz, 0.0)) + vec4(rel, 0.0);
|
||||
gl_Position = u_proj * u_trans * a_position; //u_proj * (a_position + vec4(pos.xyz * (dst - 1.0), 0.0));
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package mindustry.content;
|
||||
|
||||
import arc.graphics.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.graphics.g3d.*;
|
||||
import mindustry.maps.planet.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
@ -11,14 +13,31 @@ public class Planets implements ContentList{
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
sun = new Planet("sun", null, 3, 1){{
|
||||
detail = 6;
|
||||
generator = new TestPlanetGenerator();
|
||||
sun = new Planet("sun", null, 0, 2){{
|
||||
bloom = true;
|
||||
//lightColor = Color.valueOf("f4ee8e");
|
||||
meshLoader = () -> new SunMesh(this, 3){{
|
||||
setColors(
|
||||
Color.valueOf("ff7a38"),
|
||||
Color.valueOf("ff9638"),
|
||||
Color.valueOf("ffc64c"),
|
||||
Color.valueOf("ffc64c"),
|
||||
Color.valueOf("ffe371"),
|
||||
Color.valueOf("f4ee8e")
|
||||
);
|
||||
|
||||
scale = 1f;
|
||||
speed = 1000f;
|
||||
falloff = 0.3f;
|
||||
octaves = 4;
|
||||
spread = 1.2f;
|
||||
magnitude = 0f;
|
||||
}};
|
||||
}};
|
||||
|
||||
starter = new Planet("TODO", sun, 3, 1){{
|
||||
detail = 6;
|
||||
generator = new TestPlanetGenerator();
|
||||
meshLoader = () -> new HexMesh(this, 6);
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
@ -204,6 +204,7 @@ public class Logic implements ApplicationListener{
|
||||
@Override
|
||||
public void update(){
|
||||
Events.fire(Trigger.update);
|
||||
universe.updateGlobal();
|
||||
|
||||
if(!state.is(State.menu)){
|
||||
if(!net.client()){
|
||||
@ -211,7 +212,9 @@ public class Logic implements ApplicationListener{
|
||||
}
|
||||
|
||||
if(!state.isPaused()){
|
||||
universe.update();
|
||||
if(world.isCampaign()){
|
||||
universe.update();
|
||||
}
|
||||
Time.update();
|
||||
|
||||
if(state.rules.waves && state.rules.waveTimer && !state.gameOver){
|
||||
|
@ -1,7 +1,12 @@
|
||||
package mindustry.game;
|
||||
|
||||
import arc.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Universe{
|
||||
private long seconds;
|
||||
@ -11,6 +16,22 @@ public class Universe{
|
||||
load();
|
||||
}
|
||||
|
||||
public void updateGlobal(){
|
||||
//currently only updates one solar system
|
||||
updatePlanet(Planets.sun);
|
||||
}
|
||||
|
||||
private void updatePlanet(Planet planet){
|
||||
planet.position.setZero();
|
||||
planet.addParentOffset(planet.position);
|
||||
if(planet.parent != null){
|
||||
planet.position.add(planet.parent.position);
|
||||
}
|
||||
for(Planet child : planet.children){
|
||||
updatePlanet(child);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(){
|
||||
secondCounter += Time.delta() / 60f;
|
||||
if(secondCounter >= 1){
|
||||
@ -22,6 +43,13 @@ public class Universe{
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
//update sector light
|
||||
float light = world.getSector().getLight();
|
||||
float alpha = Mathf.clamp(Mathf.map(light, 0f, 0.8f, 0.1f, 1f));
|
||||
//assign and map so darkness is not 100% dark
|
||||
state.rules.ambientLight.a = 1f - alpha;
|
||||
state.rules.lighting = !Mathf.equal(alpha, 1f);
|
||||
}
|
||||
|
||||
public float secondsMod(float mod, float scale){
|
||||
|
@ -47,6 +47,7 @@ public class Shaders{
|
||||
|
||||
public static class PlanetShader extends LoadShader{
|
||||
public Vec3 lightDir = new Vec3(1, 1, 1).nor();
|
||||
public Color ambientColor = Color.white.cpy();
|
||||
|
||||
public PlanetShader(){
|
||||
super("planet", "planet");
|
||||
@ -55,6 +56,7 @@ public class Shaders{
|
||||
@Override
|
||||
public void apply(){
|
||||
setUniformf("u_lightdir", lightDir);
|
||||
setUniformf("u_ambientColor", ambientColor.r, ambientColor.g, ambientColor.b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,11 +64,8 @@ public class Shaders{
|
||||
public int octaves = 5;
|
||||
public float falloff = 0.5f, scale = 1f, power = 1.3f, magnitude = 0.6f, speed = 99999999999f, spread = 1.3f, seed = Mathf.random(9999f);
|
||||
|
||||
public Color[] colors;
|
||||
public float[] colorValues;
|
||||
|
||||
public Vec3 center = new Vec3();
|
||||
|
||||
public SunShader(){
|
||||
super("sun", "sun");
|
||||
}
|
||||
@ -81,22 +80,10 @@ public class Shaders{
|
||||
setUniformf("u_time", Time.globalTime() / speed);
|
||||
setUniformf("u_seed", seed);
|
||||
setUniformf("u_spread", spread);
|
||||
setUniformf("u_center", center);
|
||||
|
||||
setUniformi("u_colornum", colors.length);
|
||||
setUniformi("u_colornum", colorValues.length / 4);
|
||||
setUniform4fv("u_colors[0]", colorValues, 0, colorValues.length);
|
||||
}
|
||||
|
||||
public void updateColors(){
|
||||
colorValues = new float[colors.length*4];
|
||||
|
||||
for(int i = 0; i < colors.length; i ++){
|
||||
colorValues[i*4] = colors[i].r;
|
||||
colorValues[i*4 + 1] = colors[i].g;
|
||||
colorValues[i*4 + 2] = colors[i].b;
|
||||
colorValues[i*4 + 3] = colors[i].a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlanetGridShader extends LoadShader{
|
||||
|
@ -1,61 +0,0 @@
|
||||
package mindustry.graphics.g3d;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.VertexAttributes.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
public class GenericMesh{
|
||||
protected final float[] floats = new float[3 + 3 + 1];
|
||||
protected final int primitiveType;
|
||||
protected final Mesh mesh;
|
||||
|
||||
public GenericMesh(int vertices, int primitiveType){
|
||||
this.primitiveType = primitiveType;
|
||||
mesh = new Mesh(true, vertices, 0,
|
||||
new VertexAttribute(Usage.position, 3, Shader.positionAttribute),
|
||||
new VertexAttribute(Usage.normal, 3, Shader.normalAttribute),
|
||||
new VertexAttribute(Usage.colorPacked, 4, Shader.colorAttribute)
|
||||
);
|
||||
|
||||
mesh.getVerticesBuffer().limit(mesh.getMaxVertices());
|
||||
mesh.getVerticesBuffer().position(0);
|
||||
}
|
||||
|
||||
public void render(Mat3D mat){
|
||||
render(mat, Shaders.planet);
|
||||
}
|
||||
|
||||
public void render(Mat3D mat, Shader shader){
|
||||
shader.begin();
|
||||
shader.setUniformMatrix4("u_projModelView", mat.val);
|
||||
shader.apply();
|
||||
mesh.render(shader, primitiveType);
|
||||
shader.end();
|
||||
}
|
||||
|
||||
protected Vec3 normal(Vec3 v1, Vec3 v2, Vec3 v3){
|
||||
return Tmp.v32.set(v2).sub(v1).crs(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z).nor();
|
||||
}
|
||||
|
||||
protected void verts(Vec3 a, Vec3 b, Vec3 c, Vec3 normal, Color color){
|
||||
vert(a, normal, color);
|
||||
vert(b, normal, color);
|
||||
vert(c, normal, color);
|
||||
}
|
||||
|
||||
protected void vert(Vec3 a, Vec3 normal, Color color){
|
||||
floats[0] = a.x;
|
||||
floats[1] = a.y;
|
||||
floats[2] = a.z;
|
||||
|
||||
floats[3] = normal.x;
|
||||
floats[4] = normal.y;
|
||||
floats[5] = normal.z;
|
||||
|
||||
floats[6] = color.toFloatBits();
|
||||
mesh.getVerticesBuffer().put(floats);
|
||||
}
|
||||
}
|
18
core/src/mindustry/graphics/g3d/HexMesh.java
Normal file
18
core/src/mindustry/graphics/g3d/HexMesh.java
Normal file
@ -0,0 +1,18 @@
|
||||
package mindustry.graphics.g3d;
|
||||
|
||||
import arc.math.geom.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
public class HexMesh extends PlanetMesh{
|
||||
|
||||
public HexMesh(Planet planet, int divisions){
|
||||
super(planet, MeshBuilder.buildHex(planet.generator, divisions, false, planet.radius, 0.2f), Shaders.planet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRender(){
|
||||
Shaders.planet.lightDir.set(planet.solarSystem.position).sub(planet.position).rotate(Vec3.Y, planet.getRotation()).nor();
|
||||
Shaders.planet.ambientColor.set(planet.solarSystem.lightColor);
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import arc.graphics.*;
|
||||
import arc.math.geom.*;
|
||||
|
||||
/** Defines color and height for a planet mesh. */
|
||||
public interface PlanetMesher{
|
||||
public interface HexMesher{
|
||||
float getHeight(Vec3 position);
|
||||
Color getColor(Vec3 position);
|
||||
}
|
131
core/src/mindustry/graphics/g3d/MeshBuilder.java
Normal file
131
core/src/mindustry/graphics/g3d/MeshBuilder.java
Normal file
@ -0,0 +1,131 @@
|
||||
package mindustry.graphics.g3d;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.VertexAttributes.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.graphics.g3d.PlanetGrid.*;
|
||||
|
||||
public class MeshBuilder{
|
||||
private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3();
|
||||
private static final float[] floats = new float[3 + 3 + 1];
|
||||
private static Mesh mesh;
|
||||
|
||||
public static Mesh buildIcosphere(int divisions, float radius){
|
||||
begin(20 * (2 << (2 * divisions - 1)) * 7 * 3);
|
||||
|
||||
MeshResult result = Icosphere.create(divisions);
|
||||
for(int i = 0; i < result.indices.size; i+= 3){
|
||||
v1.set(result.vertices.items, result.indices.items[i] * 3).setLength(radius);
|
||||
v2.set(result.vertices.items, result.indices.items[i + 1] * 3).setLength(radius);
|
||||
v3.set(result.vertices.items, result.indices.items[i + 2] * 3).setLength(radius);
|
||||
|
||||
verts(v1, v3, v2, normal(v1, v2, v3).scl(-1f), Color.white);
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
public static Mesh buildHex(HexMesher mesher, int divisions, boolean lines, float radius, float intensity){
|
||||
PlanetGrid grid = PlanetGrid.create(divisions);
|
||||
|
||||
begin(grid.tiles.length * 12 * (3 + 3 + 1));
|
||||
|
||||
for(Ptile tile : grid.tiles){
|
||||
|
||||
Vec3 nor = v1.setZero();
|
||||
Corner[] c = tile.corners;
|
||||
|
||||
for(Corner corner : c){
|
||||
corner.bv.set(corner.v).setLength(radius);
|
||||
}
|
||||
|
||||
for(Corner corner : c){
|
||||
corner.v.setLength(radius + hexElevation(corner.bv, mesher, radius)*intensity);
|
||||
}
|
||||
|
||||
for(Corner corner : c){
|
||||
nor.add(corner.v);
|
||||
}
|
||||
nor.nor();
|
||||
|
||||
Vec3 realNormal = normal(c[0].v, c[2].v, c[4].v);
|
||||
nor.set(realNormal);
|
||||
|
||||
Color color = hexColor(tile.v, mesher, radius);
|
||||
|
||||
if(lines){
|
||||
nor.set(1f, 1f, 1f);
|
||||
|
||||
for(int i = 0; i < c.length; i++){
|
||||
Vec3 v1 = c[i].v;
|
||||
Vec3 v2 = c[(i + 1) % c.length].v;
|
||||
|
||||
vert(v1, nor, color);
|
||||
vert(v2, nor, color);
|
||||
}
|
||||
}else{
|
||||
verts(c[0].v, c[1].v, c[2].v, nor, color);
|
||||
verts(c[0].v, c[2].v, c[3].v, nor, color);
|
||||
verts(c[0].v, c[3].v, c[4].v, nor, color);
|
||||
|
||||
if(c.length > 5){
|
||||
verts(c[0].v, c[4].v, c[5].v, nor, color);
|
||||
}else{
|
||||
verts(c[0].v, c[3].v, c[4].v, nor, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
private static float hexElevation(Vec3 v, HexMesher mesher, float radius){
|
||||
return mesher.getHeight(v2.set(v).scl(1f / radius));
|
||||
}
|
||||
|
||||
private static Color hexColor(Vec3 v, HexMesher mesher, float radius){
|
||||
return mesher.getColor(v2.set(v).scl(1f / radius));
|
||||
}
|
||||
|
||||
private static void begin(int count){
|
||||
mesh = new Mesh(true, count, 0,
|
||||
new VertexAttribute(Usage.position, 3, Shader.positionAttribute),
|
||||
new VertexAttribute(Usage.normal, 3, Shader.normalAttribute),
|
||||
new VertexAttribute(Usage.colorPacked, 4, Shader.colorAttribute)
|
||||
);
|
||||
|
||||
mesh.getVerticesBuffer().limit(mesh.getMaxVertices());
|
||||
mesh.getVerticesBuffer().position(0);
|
||||
}
|
||||
|
||||
private static Mesh end(){
|
||||
Mesh last = mesh;
|
||||
mesh = null;
|
||||
return last;
|
||||
}
|
||||
|
||||
private static Vec3 normal(Vec3 v1, Vec3 v2, Vec3 v3){
|
||||
return Tmp.v32.set(v2).sub(v1).crs(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z).nor();
|
||||
}
|
||||
|
||||
private static void verts(Vec3 a, Vec3 b, Vec3 c, Vec3 normal, Color color){
|
||||
vert(a, normal, color);
|
||||
vert(b, normal, color);
|
||||
vert(c, normal, color);
|
||||
}
|
||||
|
||||
private static void vert(Vec3 a, Vec3 normal, Color color){
|
||||
floats[0] = a.x;
|
||||
floats[1] = a.y;
|
||||
floats[2] = a.z;
|
||||
|
||||
floats[3] = normal.x;
|
||||
floats[4] = normal.y;
|
||||
floats[5] = normal.z;
|
||||
|
||||
floats[6] = color.toFloatBits();
|
||||
mesh.getVerticesBuffer().put(floats);
|
||||
}
|
||||
}
|
@ -1,102 +1,32 @@
|
||||
package mindustry.graphics.g3d;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.graphics.g3d.PlanetGrid.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
public class PlanetMesh extends GenericMesh{
|
||||
private Vec3 vec = new Vec3();
|
||||
private PlanetGrid grid;
|
||||
private Vec3 center = new Vec3();
|
||||
/** Defines a mesh that is rendered for a planet. Subclasses provide a mesh and a shader. */
|
||||
public abstract class PlanetMesh{
|
||||
protected final Mesh mesh;
|
||||
protected final Planet planet;
|
||||
protected final Shader shader;
|
||||
|
||||
private boolean lines;
|
||||
private float radius, intensity = 0.2f;
|
||||
|
||||
private final PlanetMesher gen;
|
||||
|
||||
public PlanetMesh(int divisions, PlanetMesher gen){
|
||||
this(divisions, gen, 1f, false);
|
||||
public PlanetMesh(Planet planet, Mesh mesh, Shader shader){
|
||||
this.planet = planet;
|
||||
this.mesh = mesh;
|
||||
this.shader = shader;
|
||||
}
|
||||
|
||||
public PlanetMesh(int divisions, PlanetMesher gen, float radius, boolean lines){
|
||||
super(PlanetGrid.create(divisions).tiles.length * 12 * (3 + 3 + 1), lines ? Gl.lines : Gl.triangles);
|
||||
/** Should be overridden to set up any shader parameters such as planet position, normals, etc. */
|
||||
public abstract void preRender();
|
||||
|
||||
this.gen = gen;
|
||||
this.radius = radius;
|
||||
this.grid = PlanetGrid.create(divisions);
|
||||
this.lines = lines;
|
||||
|
||||
generateMesh();
|
||||
}
|
||||
|
||||
public @Nullable Vec3 intersect(Ray ray){
|
||||
boolean found = Intersector3D.intersectRaySphere(ray, center, radius, Tmp.v33);
|
||||
if(!found) return null;
|
||||
return Tmp.v33;
|
||||
}
|
||||
|
||||
/** @return the sector that is hit by this ray, or null if nothing intersects it. */
|
||||
public @Nullable Ptile getTile(Ray ray){
|
||||
boolean found = Intersector3D.intersectRaySphere(ray, center, radius, Tmp.v33);
|
||||
if(!found) return null;
|
||||
return Structs.findMin(grid.tiles, t -> t.v.dst(Tmp.v33));
|
||||
}
|
||||
|
||||
private void generateMesh(){
|
||||
for(Ptile tile : grid.tiles){
|
||||
|
||||
Vec3 nor = Tmp.v31.setZero();
|
||||
Corner[] c = tile.corners;
|
||||
|
||||
for(Corner corner : c){
|
||||
corner.bv.set(corner.v).setLength(radius);
|
||||
}
|
||||
|
||||
for(Corner corner : c){
|
||||
corner.v.setLength(radius + elevation(corner.bv)*intensity);
|
||||
}
|
||||
|
||||
for(Corner corner : c){
|
||||
nor.add(corner.v);
|
||||
}
|
||||
nor.nor();
|
||||
|
||||
Vec3 realNormal = normal(c[0].v, c[2].v, c[4].v);
|
||||
nor.set(realNormal);
|
||||
|
||||
Color color = color(tile.v);
|
||||
|
||||
if(lines){
|
||||
nor.set(1f, 1f, 1f);
|
||||
|
||||
for(int i = 0; i < c.length; i++){
|
||||
Vec3 v1 = c[i].v;
|
||||
Vec3 v2 = c[(i + 1) % c.length].v;
|
||||
|
||||
vert(v1, nor, color);
|
||||
vert(v2, nor, color);
|
||||
}
|
||||
}else{
|
||||
verts(c[0].v, c[1].v, c[2].v, nor, color);
|
||||
verts(c[0].v, c[2].v, c[3].v, nor, color);
|
||||
verts(c[0].v, c[3].v, c[4].v, nor, color);
|
||||
|
||||
if(c.length > 5){
|
||||
verts(c[0].v, c[4].v, c[5].v, nor, color);
|
||||
}else{
|
||||
verts(c[0].v, c[3].v, c[4].v, nor, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float elevation(Vec3 v){
|
||||
return gen.getHeight(vec.set(v).scl(1f / radius));
|
||||
}
|
||||
|
||||
private Color color(Vec3 v){
|
||||
return gen.getColor(vec.set(v).scl(1f / radius));
|
||||
public void render(Mat3D projection, Mat3D transform){
|
||||
preRender();
|
||||
shader.begin();
|
||||
shader.setUniformMatrix4("u_proj", projection.val);
|
||||
shader.setUniformMatrix4("u_trans", transform.val);
|
||||
shader.apply();
|
||||
mesh.render(shader, Gl.triangles);
|
||||
shader.end();
|
||||
}
|
||||
}
|
||||
|
11
core/src/mindustry/graphics/g3d/ShaderSphereMesh.java
Normal file
11
core/src/mindustry/graphics/g3d/ShaderSphereMesh.java
Normal file
@ -0,0 +1,11 @@
|
||||
package mindustry.graphics.g3d;
|
||||
|
||||
import arc.graphics.gl.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
public abstract class ShaderSphereMesh extends PlanetMesh{
|
||||
|
||||
public ShaderSphereMesh(Planet planet, Shader shader, int divisions){
|
||||
super(planet, MeshBuilder.buildIcosphere(divisions, planet.radius), shader);
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package mindustry.graphics.g3d;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.math.geom.*;
|
||||
|
||||
public class SphereMesh extends GenericMesh{
|
||||
private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3(), v4 = new Vec3();
|
||||
|
||||
protected final float radius;
|
||||
|
||||
public SphereMesh(int divisions, float radius){
|
||||
super(20 * (2 << (2 * divisions - 1)) * 7 * 3, Gl.triangles);
|
||||
this.radius = radius;
|
||||
|
||||
MeshResult result = Icosphere.create(divisions);
|
||||
for(int i = 0; i < result.indices.size; i+= 3){
|
||||
v1.set(result.vertices.items, result.indices.items[i] * 3).setLength(radius);
|
||||
v2.set(result.vertices.items, result.indices.items[i + 1] * 3).setLength(radius);
|
||||
v3.set(result.vertices.items, result.indices.items[i + 2] * 3).setLength(radius);
|
||||
|
||||
verts(v1, v3, v2, normal(v1, v2, v3).scl(-1f), Color.white);
|
||||
}
|
||||
}
|
||||
}
|
41
core/src/mindustry/graphics/g3d/SunMesh.java
Normal file
41
core/src/mindustry/graphics/g3d/SunMesh.java
Normal file
@ -0,0 +1,41 @@
|
||||
package mindustry.graphics.g3d;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.graphics.Shaders.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
public class SunMesh extends ShaderSphereMesh{
|
||||
public int octaves = 5;
|
||||
public float falloff = 0.5f, scale = 1f, power = 1.3f, magnitude = 0.6f, speed = 99999999999f, spread = 1.3f, seed = Mathf.random(9999f);
|
||||
public float[] colorValues;
|
||||
|
||||
public SunMesh(Planet planet, int divisions){
|
||||
super(planet, Shaders.sun, divisions);
|
||||
}
|
||||
|
||||
public void setColors(Color... colors){
|
||||
colorValues = new float[colors.length*4];
|
||||
|
||||
for(int i = 0; i < colors.length; i ++){
|
||||
colorValues[i*4] = colors[i].r;
|
||||
colorValues[i*4 + 1] = colors[i].g;
|
||||
colorValues[i*4 + 2] = colors[i].b;
|
||||
colorValues[i*4 + 3] = colors[i].a;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRender(){
|
||||
SunShader s = (SunShader)shader;
|
||||
s.octaves = octaves;
|
||||
s.falloff = falloff;
|
||||
s.scale = scale;
|
||||
s.power = power;
|
||||
s.magnitude = magnitude;
|
||||
s.speed = speed;
|
||||
s.seed = seed;
|
||||
s.colorValues = colorValues;
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package mindustry.maps.generators;
|
||||
|
||||
import arc.math.geom.*;
|
||||
import mindustry.graphics.g3d.PlanetMesher;
|
||||
import mindustry.graphics.g3d.HexMesher;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public abstract class PlanetGenerator extends BasicGenerator implements PlanetMesher{
|
||||
public abstract class PlanetGenerator extends BasicGenerator implements HexMesher{
|
||||
protected Sector sector;
|
||||
|
||||
protected void genTile(Vec3 position, TileGen tile){
|
||||
|
@ -1,12 +1,13 @@
|
||||
package mindustry.type;
|
||||
|
||||
import arc.files.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ctype.*;
|
||||
@ -19,17 +20,19 @@ import static mindustry.Vars.universe;
|
||||
|
||||
public class Planet extends UnlockableContent{
|
||||
/** Default spacing between planet orbits in world units. */
|
||||
private static final float orbitSpacing = 6f;
|
||||
private static final float orbitSpacing = 5f;
|
||||
/** intersect() temp var. */
|
||||
private static final Vec3 intersectResult = new Vec3();
|
||||
/** Mesh used for rendering. Created on load() - will be null on the server! */
|
||||
public GenericMesh mesh;
|
||||
/** Grid used for the sectors on the planet. */
|
||||
public @NonNull PlanetGrid grid;
|
||||
/** Generator that will make the planet. */
|
||||
public @NonNull PlanetGenerator generator;
|
||||
public PlanetMesh mesh;
|
||||
/** 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. */
|
||||
public @Nullable PlanetGrid grid;
|
||||
/** Generator that will make the planet. Can be null for planets that don't need to be landed on. */
|
||||
public @Nullable PlanetGenerator generator;
|
||||
/** Array of sectors; directly maps to tiles in the grid. */
|
||||
public @NonNull Array<Sector> sectors;
|
||||
/** Detail in divisions. Must be between 1 and 10. 6 is a good number for this.*/
|
||||
public int detail = 3;
|
||||
/** Radius of this planet's sphere. Does not take into account sattelites. */
|
||||
public float radius;
|
||||
/** Orbital radius around the sun. Do not change unless you know exactly what you are doing.*/
|
||||
@ -42,26 +45,52 @@ public class Planet extends UnlockableContent{
|
||||
public float rotateTime = 24f * 60f;
|
||||
/** Whether this planet is tidally locked relative to its parent - see https://en.wikipedia.org/wiki/Tidal_locking */
|
||||
public boolean tidalLock = false;
|
||||
/** Whether the bloom render effect is enabled. */
|
||||
public boolean bloom = false;
|
||||
/** For suns, this is the color that shines on other planets. Does nothing for children. */
|
||||
public Color lightColor = Color.white.cpy();
|
||||
/** Parent body that this planet orbits around. If null, this planet is considered to be in the middle of the solar system.*/
|
||||
public @Nullable Planet parent;
|
||||
/** The root parent of the whole solar system this planet is in. */
|
||||
public @NonNull Planet solarSystem;
|
||||
/** All planets orbiting this one, in ascending order of radius. */
|
||||
public Array<Planet> children = new Array<>();
|
||||
/** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */
|
||||
protected Prov<PlanetMesh> meshLoader = () -> new SunMesh(this, 2);
|
||||
|
||||
public Planet(String name, Planet parent, int size, float radius){
|
||||
public Planet(String name, Planet parent, int sectorSize, float radius){
|
||||
super(name);
|
||||
|
||||
this.radius = radius;
|
||||
this.parent = parent;
|
||||
|
||||
grid = PlanetGrid.create(size);
|
||||
if(sectorSize > 0){
|
||||
grid = PlanetGrid.create(sectorSize);
|
||||
|
||||
sectors = new Array<>(grid.tiles.length);
|
||||
for(int i = 0; i < grid.tiles.length; i++){
|
||||
sectors.add(new Sector(this, grid.tiles[i], new SectorData()));
|
||||
sectors = new Array<>(grid.tiles.length);
|
||||
for(int i = 0; i < grid.tiles.length; i++){
|
||||
sectors.add(new Sector(this, grid.tiles[i], new SectorData()));
|
||||
}
|
||||
|
||||
//read data for sectors
|
||||
Fi data = Vars.tree.get("planets/" + name + ".dat");
|
||||
if(data.exists()){
|
||||
try(Reads read = data.reads()){
|
||||
short dsize = read.s();
|
||||
for(int i = 0; i < dsize; i++){
|
||||
sectors.get(i).data.read(read);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
sectors = new Array<>();
|
||||
}
|
||||
|
||||
//total radius is initially just the radius
|
||||
totalRadius += radius;
|
||||
|
||||
//get orbit radius by extending past the parent's total radius
|
||||
orbitRadius = parent == null ? 0f : (parent.totalRadius + orbitSpacing + radius);
|
||||
orbitRadius = parent == null ? 0f : (parent.totalRadius + orbitSpacing + totalRadius);
|
||||
|
||||
//orbit time is based on radius [kepler's third law]
|
||||
orbitTime = Mathf.pow(orbitRadius, 1.5f) * 1000;
|
||||
@ -72,19 +101,12 @@ public class Planet extends UnlockableContent{
|
||||
parent.updateTotalRadius();
|
||||
}
|
||||
|
||||
//read data
|
||||
Fi data = Vars.tree.get("planets/" + name + ".dat");
|
||||
if(data.exists()){
|
||||
try(Reads read = data.reads()){
|
||||
short dsize = read.s();
|
||||
for(int i = 0; i < dsize; i++){
|
||||
sectors.get(i).data.read(read);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//TODO crash instead - this is a critical error!
|
||||
Log.err("Planet {0} is missing its data file.", name);
|
||||
}
|
||||
//calculate solar system
|
||||
for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent);
|
||||
}
|
||||
|
||||
public boolean isLandable(){
|
||||
return grid != null && generator != null && sectors.size > 0;
|
||||
}
|
||||
|
||||
public void updateTotalRadius(){
|
||||
@ -99,7 +121,7 @@ public class Planet extends UnlockableContent{
|
||||
public float getOrbitAngle(){
|
||||
//applies random offset to prevent planets from starting out in a line
|
||||
float offset = Mathf.randomSeed(id, 360);
|
||||
return (offset + universe.seconds() / (orbitTime / 360f)) % 360f;
|
||||
return (offset + universe.secondsf() / (orbitTime / 360f)) % 360f;
|
||||
}
|
||||
|
||||
/** Calulates rotation on own axis based on universe time.*/
|
||||
@ -110,7 +132,7 @@ public class Planet extends UnlockableContent{
|
||||
}
|
||||
//random offset for more variability
|
||||
float offset = Mathf.randomSeed(id+1, 360);
|
||||
return (offset + universe.seconds() / (rotateTime / 360f)) % 360f;
|
||||
return (offset + universe.secondsf() / (rotateTime / 360f)) % 360f;
|
||||
}
|
||||
|
||||
/** Adds this planet's offset relative to its parent to the vector. Used for calculating world positions. */
|
||||
@ -121,7 +143,7 @@ public class Planet extends UnlockableContent{
|
||||
}
|
||||
|
||||
float angle = getOrbitAngle();
|
||||
return in.add(Angles.trnsx(angle, orbitRadius), Angles.trnsy(angle, orbitRadius), 0f);
|
||||
return in.add(Angles.trnsx(angle, orbitRadius), 0, Angles.trnsy(angle, orbitRadius));
|
||||
}
|
||||
|
||||
/** Gets the absolute world position of this planet, taking into account all parents. O(n) complexity.*/
|
||||
@ -133,9 +155,14 @@ public class Planet extends UnlockableContent{
|
||||
return in;
|
||||
}
|
||||
|
||||
/** @return the supplied matrix with transformation applied. */
|
||||
public Mat3D getTransform(Mat3D mat){
|
||||
return mat.setToTranslation(position).rotate(Vec3.Y, getRotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
mesh = new PlanetMesh(detail, generator);
|
||||
mesh = meshLoader.get();
|
||||
}
|
||||
|
||||
/** Gets a sector a tile position. */
|
||||
@ -143,13 +170,24 @@ public class Planet extends UnlockableContent{
|
||||
return sectors.get(tile.id);
|
||||
}
|
||||
|
||||
/** @return the sector that is hit by this ray, or null if nothing intersects it.
|
||||
* @param center the center of this planet in 3D space, usually (0,0,0). */
|
||||
public @Nullable Sector getSector(Vec3 center, Ray ray){
|
||||
boolean found = Intersector3D.intersectRaySphere(ray, center, radius, Tmp.v33);
|
||||
/** @return the sector that is hit by this ray, or null if nothing intersects it. */
|
||||
public @Nullable Sector getSector(Ray ray){
|
||||
return getSector(ray, radius);
|
||||
}
|
||||
|
||||
/** @return the sector that is hit by this ray, or null if nothing intersects it. */
|
||||
public @Nullable Sector getSector(Ray ray, float radius){
|
||||
Vec3 vec = intersect(ray, radius);
|
||||
if(vec == null) return null;
|
||||
vec.sub(position).rotate(Vec3.Y, getRotation());
|
||||
return sectors.min(t -> t.tile.v.dst2(vec));
|
||||
}
|
||||
|
||||
/** @return the sector that is hit by this ray, or null if nothing intersects it. */
|
||||
public @Nullable Vec3 intersect(Ray ray, float radius){
|
||||
boolean found = Intersector3D.intersectRaySphere(ray, position, radius, intersectResult);
|
||||
if(!found) return null;
|
||||
//TODO fix O(N) search
|
||||
return sectors.min(t -> t.tile.v.dst(Tmp.v33));
|
||||
return intersectResult;
|
||||
}
|
||||
|
||||
/** Planets cannot be viewed in the database dialog. */
|
||||
|
@ -34,6 +34,14 @@ public class Sector{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/** @return light dot product in the range [0, 1]. */
|
||||
public float getLight(){
|
||||
Vec3 normal = Tmp.v31.set(tile.v).rotate(Vec3.Y, -planet.getRotation()).nor();
|
||||
Vec3 light = Tmp.v32.set(planet.solarSystem.position).sub(planet.position).nor();
|
||||
//lightness in [0, 1]
|
||||
return (normal.dot(light) + 1f) / 2f;
|
||||
}
|
||||
|
||||
public int getSize(){
|
||||
return (int)(rect.radius * 3200);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.g3d.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.input.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
@ -34,16 +35,16 @@ public class PlanetDialog extends FloatingDialog{
|
||||
//the base planet that's being rendered
|
||||
private final Planet solarSystem = Planets.sun;
|
||||
|
||||
private final PlanetMesh[] outlines = new PlanetMesh[10];
|
||||
private final Mesh[] outlines = new Mesh[10];
|
||||
private final Camera3D cam = new Camera3D();
|
||||
private final VertexBatch3D batch = new VertexBatch3D(false, true, 0);
|
||||
private final PlaneBatch3D projector = new PlaneBatch3D();
|
||||
private final Mat3D mat = new Mat3D();
|
||||
private final Vec3 camRelative = new Vec3();
|
||||
|
||||
|
||||
private final SphereMesh sun = new SphereMesh(3, 1.2f);
|
||||
private final Bloom bloom = new Bloom(false){{
|
||||
private final Bloom bloom = new Bloom(Core.graphics.getWidth()/4, Core.graphics.getHeight()/4, true, false, true){{
|
||||
setClearColor(0, 0, 0, 0);
|
||||
blurPasses = 6;
|
||||
}};
|
||||
|
||||
private Planet planet = Planets.starter;
|
||||
@ -57,31 +58,34 @@ public class PlanetDialog extends FloatingDialog{
|
||||
addCloseButton();
|
||||
buttons.addImageTextButton("$techtree", Icon.tree, () -> ui.tech.show()).size(230f, 64f);
|
||||
|
||||
Tmp.v1.trns(0, camLength);
|
||||
cam.position.set(Tmp.v1.x, 0f, Tmp.v1.y);
|
||||
camRelative.set(0, 0f, camLength);
|
||||
projector.setScaling(1f / 300f);
|
||||
|
||||
update(() -> {
|
||||
Ptile tile = outline(planet.grid.size).getTile(cam.getPickRay(Core.input.mouseX(), Core.input.mouseY()));
|
||||
hovered = tile == null ? null : planet.getSector(tile);
|
||||
|
||||
Vec3 v = Tmp.v33.set(Core.input.mouseX(), Core.input.mouseY(), 0);
|
||||
|
||||
if(Core.input.keyDown(KeyCode.MOUSE_LEFT)){
|
||||
float upV = cam.position.angle(Vec3.Y);
|
||||
float xscale = 9f, yscale = 10f;
|
||||
float margin = 1;
|
||||
if(planet.isLandable()){
|
||||
hovered = planet.getSector(cam.getMouseRay(), outlineRad);
|
||||
|
||||
//scale X speed depending on polar coordinate
|
||||
float speed = 1f - Math.abs(upV - 90) / 90f;
|
||||
if(Core.input.keyDown(KeyCode.MOUSE_LEFT)){
|
||||
float upV = camRelative.angle(Vec3.Y);
|
||||
float xscale = 9f, yscale = 10f;
|
||||
float margin = 1;
|
||||
|
||||
cam.position.rotate(cam.up, (v.x - lastX) / xscale * speed);
|
||||
//scale X speed depending on polar coordinate
|
||||
float speed = 1f - Math.abs(upV - 90) / 90f;
|
||||
|
||||
//prevent user from scrolling all the way up and glitching it out
|
||||
float amount = (v.y - lastY) / yscale;
|
||||
amount = Mathf.clamp(upV + amount, margin, 180f - margin) - upV;
|
||||
camRelative.rotate(cam.up, (v.x - lastX) / xscale * speed);
|
||||
|
||||
cam.position.rotate(Tmp.v31.set(cam.up).rotate(cam.direction, 90), amount);
|
||||
//prevent user from scrolling all the way up and glitching it out
|
||||
float amount = (v.y - lastY) / yscale;
|
||||
amount = Mathf.clamp(upV + amount, margin, 180f - margin) - upV;
|
||||
|
||||
camRelative.rotate(Tmp.v31.set(cam.up).rotate(cam.direction, 90), amount);
|
||||
}
|
||||
|
||||
}else{
|
||||
hovered = selected = null;
|
||||
}
|
||||
|
||||
lastX = v.x;
|
||||
@ -110,23 +114,6 @@ public class PlanetDialog extends FloatingDialog{
|
||||
stable.pack();
|
||||
stable.setPosition(0, 0, Align.center);
|
||||
|
||||
Shaders.sun.colors = new Color[]{
|
||||
Color.valueOf("ff7a38"),
|
||||
Color.valueOf("ff9638"),
|
||||
Color.valueOf("ffc64c"),
|
||||
Color.valueOf("ffc64c"),
|
||||
Color.valueOf("ffe371"),
|
||||
Color.valueOf("f4ee8e"),
|
||||
};
|
||||
|
||||
Shaders.sun.updateColors();
|
||||
Shaders.sun.scale = 1f;
|
||||
Shaders.sun.speed = 1000f;
|
||||
Shaders.sun.falloff = 0.3f;
|
||||
Shaders.sun.octaves = 4;
|
||||
Shaders.sun.spread = 1.2f;
|
||||
Shaders.sun.magnitude = 0f;
|
||||
|
||||
shown(this::setup);
|
||||
}
|
||||
|
||||
@ -149,16 +136,80 @@ public class PlanetDialog extends FloatingDialog{
|
||||
cam.up.set(Vec3.Y);
|
||||
|
||||
cam.resize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
||||
cam.lookAt(0, 0, 0);
|
||||
cam.position.set(planet.position).add(camRelative);
|
||||
cam.lookAt(planet.position);
|
||||
cam.update();
|
||||
|
||||
projector.proj(cam.combined());
|
||||
batch.proj(cam.combined());
|
||||
|
||||
renderPlanet(solarSystem);
|
||||
bloom.capture();
|
||||
|
||||
//renderSun();
|
||||
//renderPlanet();
|
||||
renderPlanet(solarSystem);
|
||||
if(planet.isLandable()){
|
||||
//TODO
|
||||
renderSectors(planet);
|
||||
}
|
||||
|
||||
if(false)
|
||||
Draw.batch(projector, () -> {
|
||||
if(selected != null){
|
||||
setPlane(selected);
|
||||
stable.draw();
|
||||
}
|
||||
});
|
||||
|
||||
bloom.render();
|
||||
|
||||
Gl.disable(Gl.cullFace);
|
||||
//Gl.disable(Gl.depthTest);
|
||||
|
||||
if(false && selected != null){
|
||||
Vec3 pos = cam.project(Tmp.v31.set(selected.tile.v).setLength(outlineRad));
|
||||
stable.setPosition(pos.x, pos.y, Align.center);
|
||||
stable.draw();
|
||||
}
|
||||
|
||||
cam.update();
|
||||
}
|
||||
|
||||
private void renderPlanet(Planet planet){
|
||||
//render planet at offsetted position in the world
|
||||
|
||||
if(false){
|
||||
bloom.capture();
|
||||
}
|
||||
|
||||
planet.mesh.render(cam.combined(), planet.getTransform(mat));
|
||||
|
||||
if(false){
|
||||
bloom.render();
|
||||
|
||||
Gl.enable(Gl.depthTest);
|
||||
Gl.enable(Gl.blend);
|
||||
Gl.depthMask(true);
|
||||
}
|
||||
|
||||
renderOrbit(planet);
|
||||
|
||||
for(Planet child : planet.children){
|
||||
renderPlanet(child);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderOrbit(Planet planet){
|
||||
if(planet.parent == null) return;
|
||||
|
||||
Vec3 center = planet.parent.position;
|
||||
float radius = planet.orbitRadius;
|
||||
int points = (int)(radius * 50);
|
||||
Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray));
|
||||
batch.flush(Gl.lineLoop);
|
||||
}
|
||||
|
||||
private void renderSectors(Planet planet){
|
||||
//apply transformed position
|
||||
batch.proj().mul(planet.getTransform(mat));
|
||||
|
||||
for(Sector sec : planet.sectors){
|
||||
if(sec.save == null){
|
||||
@ -184,67 +235,19 @@ public class PlanetDialog extends FloatingDialog{
|
||||
|
||||
batch.flush(Gl.triangles);
|
||||
|
||||
if(true)
|
||||
Draw.batch(projector, () -> {
|
||||
if(selected != null){
|
||||
setPlane(selected);
|
||||
stable.draw();
|
||||
}
|
||||
});
|
||||
//render sector grid
|
||||
Mesh mesh = outline(planet.grid.size);
|
||||
Shader shader = Shaders.planetGrid;
|
||||
Vec3 tile = planet.intersect(cam.getMouseRay(), outlineRad);
|
||||
//Log.info(tile);
|
||||
Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile.sub(planet.position).rotate(Vec3.Y, planet.getRotation()), 0.2f);
|
||||
|
||||
//3D aligned table
|
||||
|
||||
Gl.disable(Gl.cullFace);
|
||||
Gl.disable(Gl.depthTest);
|
||||
|
||||
if(false && selected != null){
|
||||
Vec3 pos = cam.project(Tmp.v31.set(selected.tile.v).setLength(outlineRad));
|
||||
stable.setPosition(pos.x, pos.y, Align.center);
|
||||
stable.draw();
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPlanet(Planet planet){
|
||||
//render planet at offsetted position in the world
|
||||
Vec3 position = planet.getWorldPosition(Tmp.v33);
|
||||
mat.set(cam.combined()).trn(position); //TODO this probably won't give the desired result
|
||||
planet.mesh.render(mat);
|
||||
|
||||
renderOrbit(planet);
|
||||
|
||||
for(Planet child : planet.children){
|
||||
renderPlanet(child);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderOrbit(Planet planet){
|
||||
if(planet.parent == null) return;
|
||||
|
||||
Vec3 center = planet.parent.getWorldPosition(Tmp.v31);
|
||||
float radius = planet.radius;
|
||||
int points = (int)(radius * 10);
|
||||
Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray));
|
||||
batch.flush(Gl.lineLoop);
|
||||
}
|
||||
|
||||
private void renderPlanet(){
|
||||
PlanetMesh outline = outline(planet.grid.size);
|
||||
Vec3 tile = outline.intersect(cam.getPickRay(Core.input.mouseX(), Core.input.mouseY()));
|
||||
Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile, 0.2f);
|
||||
Shaders.planet.lightDir.set(Shaders.sun.center).nor();
|
||||
|
||||
planet.mesh.render(cam.combined());
|
||||
outline.render(cam.combined(), Shaders.planetGrid);
|
||||
}
|
||||
|
||||
private void renderSun(){
|
||||
bloom.capture();
|
||||
Shaders.sun.center.set(-3f, 0f, 0).rotate(Vec3.Y, Time.time() / 3f);
|
||||
sun.render(cam.combined(), Shaders.sun);
|
||||
bloom.render();
|
||||
|
||||
Gl.enable(Gl.depthTest);
|
||||
Gl.enable(Gl.blend);
|
||||
shader.begin();
|
||||
shader.setUniformMatrix4("u_proj", cam.combined().val);
|
||||
shader.setUniformMatrix4("u_trans", planet.getTransform(mat).val);
|
||||
shader.apply();
|
||||
mesh.render(shader, Gl.lines);
|
||||
shader.end();
|
||||
}
|
||||
|
||||
private void drawBorders(Sector sector, Color base){
|
||||
@ -305,6 +308,8 @@ public class PlanetDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
private void setPlane(Sector sector){
|
||||
float rotation = planet.getRotation();
|
||||
|
||||
projector.setPlane(
|
||||
//origin on sector position
|
||||
Tmp.v33.set(sector.tile.v).setLength(outlineRad + 0.1f),
|
||||
@ -340,9 +345,9 @@ public class PlanetDialog extends FloatingDialog{
|
||||
}
|
||||
}
|
||||
|
||||
private PlanetMesh outline(int size){
|
||||
private Mesh outline(int size){
|
||||
if(outlines[size] == null){
|
||||
outlines[size] = new PlanetMesh(size, new PlanetMesher(){
|
||||
outlines[size] = MeshBuilder.buildHex(new HexMesher(){
|
||||
@Override
|
||||
public float getHeight(Vec3 position){
|
||||
return 0;
|
||||
@ -352,7 +357,7 @@ public class PlanetDialog extends FloatingDialog{
|
||||
public Color getColor(Vec3 position){
|
||||
return outlineColor;
|
||||
}
|
||||
}, outlineRad, true);
|
||||
}, size, true, outlineRad, 0.2f);
|
||||
}
|
||||
return outlines[size];
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
org.gradle.daemon=true
|
||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||
archash=bff072e2d671c74a32b41353125c2aa6ba8c0314
|
||||
archash=17caa50a75e98000d6e7bd1568a932a087dc09c3
|
||||
|
Loading…
Reference in New Issue
Block a user