Files
Mindustry/core/src/mindustry/graphics/g3d/MeshBuilder.java
2023-05-18 11:54:30 -04:00

161 lines
4.8 KiB
Java

package mindustry.graphics.g3d;
import arc.graphics.*;
import arc.math.geom.*;
import mindustry.graphics.g3d.PlanetGrid.*;
import mindustry.maps.generators.*;
public class MeshBuilder{
private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3(), v4 = new Vec3();
private static final float[] floats = new float[3 + 3 + 1];
private static Mesh mesh;
public static Mesh buildIcosphere(int divisions, float radius, Color color){
begin(20 * (2 << (2 * divisions - 1)) * 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);
}
return end();
}
public static Mesh buildIcosphere(int divisions, float radius){
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);
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
public float getHeight(Vec3 position){
return 0;
}
@Override
public Color getColor(Vec3 position){
return color;
}
}, divisions, lines, radius, 0);
}
public static Mesh buildHex(HexMesher mesher, int divisions, boolean lines, float radius, float intensity){
PlanetGrid grid = PlanetGrid.create(divisions);
if(mesher instanceof PlanetGenerator generator){
generator.seed = generator.baseSeed;
}
begin(grid.tiles.length * 12);
for(Ptile tile : grid.tiles){
if(mesher.skip(tile.v)){
continue;
}
Corner[] c = tile.corners;
for(Corner corner : c){
corner.v.setLength((1f + mesher.getHeight(v2.set(corner.v)) * intensity) * radius);
}
Vec3 nor = normal(c[0].v, c[2].v, c[4].v);
Color color = mesher.getColor(v2.set(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);
}
}
//restore mutated corners
for(Corner corner : c){
corner.v.nor();
}
}
return end();
}
private static void begin(int count){
mesh = new Mesh(true, count, 0,
VertexAttribute.position3,
VertexAttribute.normal,
VertexAttribute.color
);
mesh.getVerticesBuffer().limit(mesh.getVerticesBuffer().capacity());
mesh.getVerticesBuffer().position(0);
}
private static Mesh end(){
Mesh last = mesh;
last.getVerticesBuffer().limit(last.getVerticesBuffer().position());
mesh = null;
return last;
}
private static Vec3 normal(Vec3 v1, Vec3 v2, Vec3 v3){
return v4.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);
}
}