001package com.fs.starfarer.api.impl.campaign.procgen; 002 003import org.lwjgl.util.vector.Vector2f; 004 005import com.fs.starfarer.api.impl.campaign.terrain.BaseTiledTerrain; 006import com.fs.starfarer.api.util.Misc; 007 008public class NebulaEditor { 009 010 protected BaseTiledTerrain plugin; 011 protected int [][] tiles; 012 protected int [][] orig; 013 protected float ts; 014 protected float width, height; 015 protected float cx, cy; 016 protected int w, h; 017 private float [][] noise; 018 019 020 public NebulaEditor(BaseTiledTerrain plugin) { 021 this.plugin = plugin; 022 tiles = plugin.getTiles(); 023 ts = plugin.getTileSize(); 024 025 width = tiles.length * ts; 026 height = tiles[0].length * ts; 027 028 cx = plugin.getEntity().getLocation().x; 029 cy = plugin.getEntity().getLocation().y; 030 031 w = tiles.length; 032 h = tiles[0].length; 033 034 orig = getTilesCopy(); 035 036 regenNoise(); 037 } 038 039 public int[][] getTilesCopy() { 040 int [][] copy = new int[w][h]; 041 for (int i = 0; i < w; i++) { 042 for (int j = 0; j < h; j++) { 043 copy[i][j] = tiles[i][j]; 044 } 045 } 046 return copy; 047 } 048 049 public int[][] getTiles() { 050 return tiles; 051 } 052 053 public int[][] getOrigTiles() { 054 return orig; 055 } 056 057 public float getTileSize() { 058 return ts; 059 } 060 061 public void regenNoise() { 062 float spikes = 1f; 063 noise = Misc.initNoise(StarSystemGenerator.random, w, h, spikes); 064 Misc.genFractalNoise(StarSystemGenerator.random, noise, 0, 0, w - 1, h - 1, 1, spikes); 065 Misc.normalizeNoise(noise); 066 067// // bug in noise generation? last line doesn't seem to have high enough values 068 // never mind, noise has to be power of two-sized 069// for (int i = 0; i < w; i++) { 070// noise[i][h - 1] = noise[i][h - 2]; 071// } 072 } 073 074// public void noisePrune(float fractionKeep) { 075// if (noise == null) regenNoise(); 076// int count = 0; 077// for (int i = 0; i < w; i++) { 078// for (int j = 0; j < h; j++) { 079// if (noise[i][j] < 1f - fractionKeep) { 080// tiles[i][j] = -1; 081// count++; 082// } 083// } 084// } 085// //System.out.println("Pruned " + (int)((count * 100f) / (float) (w * h)) + "% with keep=" + fractionKeep); 086// } 087 088 public void noisePrune(float fractionKeep) { 089 if (noise == null) regenNoise(); 090 float [] counts = new float[100]; 091 for (int i = 0; i < w; i++) { 092 for (int j = 0; j < h; j++) { 093 float f = noise[i][j]; 094 int index = (int) (f * 100f); 095 if (index < 0) index = 0; 096 if (index > 99) index = 99; 097 counts[index]++; 098 } 099 } 100 101 float total = w * h; 102 float keep = fractionKeep * total; 103 float threshold = 0f; 104 float totalKept = 0f; 105 for (int i = 0; i < 100; i++) { 106 totalKept += counts[i]; 107 if (totalKept >= keep) { 108 threshold = (float) i / 100f; 109 break; 110 } 111 } 112 113 int count = 0; 114 for (int i = 0; i < w; i++) { 115 for (int j = 0; j < h; j++) { 116 if (noise[i][j] > threshold) { 117 tiles[i][j] = -1; 118 count++; 119 } 120 } 121 } 122 //System.out.println("Pruned " + (int)((count * 100f) / (float) (w * h)) + "% with keep=" + fractionKeep); 123 } 124 125 126 public void clearArc(float x, float y, float innerRadius, float outerRadius, float startAngle, float endAngle) { 127 clearArc(x, y, innerRadius, outerRadius, startAngle, endAngle, 0f); 128 } 129 130 public void clearArc(float x, float y, float innerRadius, float outerRadius, float startAngle, float endAngle, float noiseThresholdToClear) { 131 clearArc(x, y, innerRadius, outerRadius, startAngle, endAngle, 1f, noiseThresholdToClear); 132 } 133 134 public void clearArc(float x, float y, float innerRadius, float outerRadius, float startAngle, float endAngle, float endRadiusMult, float noiseThresholdToClear) { 135 float circumference = (float) Math.PI * 2f * outerRadius; 136 float degreesPerIteration = 360f / (circumference / (ts * 0.5f)); 137 138 for (float angle = startAngle; angle < endAngle; angle += degreesPerIteration) { 139 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(angle); 140 float distMult = 1f; 141 if (endAngle > startAngle) { 142 float p = (angle - startAngle) / (endAngle - startAngle); 143 distMult = 1f + (endRadiusMult - 1f) * p; 144 } 145 146 //for (float dist = innerRadius; dist <= outerRadius; dist += ts * 0.5f) { 147 for (float dist = innerRadius * distMult; dist <= innerRadius * distMult + (outerRadius - innerRadius); dist += ts * 0.5f) { 148 Vector2f curr = new Vector2f(dir); 149 //curr.scale(dist * distMult); 150 curr.scale(dist); 151 curr.x += x; 152 curr.y += y; 153 setTileAt(curr.x, curr.y, -1, noiseThresholdToClear, setToOrigInsteadOfClear); 154 } 155 } 156 } 157 158 protected boolean setToOrigInsteadOfClear = false; 159 public boolean isSetToOrigInsteadOfClear() { 160 return setToOrigInsteadOfClear; 161 } 162 public void setSetToOrigInsteadOfClear(boolean setToOrigInsteadOfClear) { 163 this.setToOrigInsteadOfClear = setToOrigInsteadOfClear; 164 } 165 166 public void setTileAt(float x, float y, int value) { 167 setTileAt(x, y, value, 0f); 168 } 169 170 public void setTileAt(float x, float y, int value, float noiseThresholdToClear) { 171 setTileAt(x, y, value, noiseThresholdToClear, false); 172 } 173 public void setTileAt(float x, float y, int value, float noiseThresholdToClear, boolean setToOrigTile) { 174 int cellX = (int) ((width / 2f + x - cx) / ts); 175 int cellY = (int) ((height / 2f + y - cy) / ts); 176 177// if (cellX < 0) cellX = 0; 178// if (cellY < 0) cellY = 0; 179// if (cellX > tiles.length - 1) cellX = tiles.length - 1; 180// if (cellY > tiles[0].length - 1) cellY = tiles[0].length - 1; 181 182 if (cellX < 0) return; 183 if (cellY < 0) return; 184 if (cellX > tiles.length - 1) return; 185 if (cellY > tiles[0].length - 1) return; 186// if (cellX < 0) cellX = 0; 187// if (cellY < 0) cellY = 0; 188// if (cellX > tiles.length - 1) cellX = tiles.length - 1; 189// if (cellY > tiles[0].length - 1) cellY = tiles[0].length - 1; 190 191 if (setToOrigTile) { 192 value = orig[cellX][cellY]; 193 } 194 if (noiseThresholdToClear <= 0 || noise[cellX][cellY] > noiseThresholdToClear) { 195 tiles[cellX][cellY] = value; 196 } 197 //tiles[cellX][tiles[0].length - 1] = -1; 198 } 199 200 201 202} 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219