Gras (Textur) Pinsel Bugs behoben

This commit is contained in:
2026-08-21 15:47:31 +02:00
parent 03dcfb4187
commit 08e1df06d4
3 changed files with 63 additions and 11 deletions

View File

@@ -147,6 +147,33 @@ public class PlacedObjectState extends BaseAppState {
grassNode = new Node("grassNode");
((SimpleApplication) app).getRootNode().attachChild(grassNode);
applyAllSlotMaterials();
initAspectRatios();
}
private void initAspectRatios() {
String[] allPaths = new String[8];
allPaths[0] = input.grassTexturePath != null ? input.grassTexturePath : "";
String[] slots = input.grassTextureSlots;
for (int i = 0; i < 7; i++) {
allPaths[i + 1] = (i < slots.length && slots[i] != null) ? slots[i] : "";
}
float[] ars = input.grassAspectRatios.clone();
for (int s = 0; s < 8; s++) {
String p = allPaths[s];
if (p == null || p.isEmpty()) continue;
try {
com.jme3.texture.Texture tex = assetManager.loadTexture(
new com.jme3.asset.TextureKey(p, false));
if (tex != null && tex.getImage() != null) {
int w = tex.getImage().getWidth();
int h = tex.getImage().getHeight();
if (w > 0 && h > 0) ars[s] = (float) w / h;
}
} catch (Exception e) {
log.debug("[PlacedObjectState] Aspect-Ratio nicht lesbar für Slot {}: {}", s, e.getMessage());
}
}
input.grassAspectRatios = ars;
}
@Override

View File

@@ -36,18 +36,18 @@ public class GrassState extends BaseAppState
private static final Logger log = LoggerFactory.getLogger(GrassState.class);
private static final int TERRAIN_HALF = 2048;
private static final int CHUNK_SIZE = 128;
private static final int CHUNKS_PER_AXIS = (TERRAIN_HALF * 2) / CHUNK_SIZE; // 32
private static final int CHUNK_COUNT = CHUNKS_PER_AXIS * CHUNKS_PER_AXIS; // 1024
private static final int CHUNK_SIZE = de.blight.common.ChunkTerrainIO.CHUNK_SIZE; // 128
private static final int TERRAIN_HALF = de.blight.common.ChunkTerrainIO.WORLD_SIZE / 2; // 1024
private static final int CHUNKS_PER_AXIS = de.blight.common.ChunkTerrainIO.CHUNKS_PER_AXIS; // 16
private static final int CHUNK_COUNT = de.blight.common.ChunkTerrainIO.CHUNK_COUNT; // 256
private static final int BLADES_PER_TUFT = 4;
private static final float TUFT_SPREAD = 0.5f;
private static final float BLADE_WIDTH = 0.18f;
private static final int INIT_PER_FRAME = 4;
private final TerrainChunkState terrainChunkState;
private Node grassNode;
private Node grassNode;
private float[] slotAspectRatios = new float[8];
@SuppressWarnings({"unchecked", "rawtypes"})
private final List<GrassTuft>[] chunkTufts = new List[CHUNK_COUNT];
@@ -69,8 +69,9 @@ public class GrassState extends BaseAppState
for (int i = 0; i < CHUNK_COUNT; i++) chunkTufts[i] = new ArrayList<>();
GrassTuftIO.GrassData data = null;
try {
GrassTuftIO.GrassData data = GrassTuftIO.load();
data = GrassTuftIO.load();
if (data != null) {
initSlotMaterials(app.getAssetManager(), data.slotPaths());
for (GrassTuft t : data.tufts()) {
@@ -85,6 +86,28 @@ public class GrassState extends BaseAppState
if (slotMaterials.isEmpty()) {
slotMaterials.put(0, buildGrassMat(app.getAssetManager(), ""));
}
initAspectRatios(app.getAssetManager(),
data != null ? data.slotPaths() : null);
}
private void initAspectRatios(AssetManager assets, String[] slotPaths) {
java.util.Arrays.fill(slotAspectRatios, 1f);
if (slotPaths == null) return;
for (int s = 0; s < Math.min(slotAspectRatios.length, slotPaths.length); s++) {
String p = slotPaths[s];
if (p == null || p.isEmpty()) continue;
try {
com.jme3.texture.Texture tex = assets.loadTexture(
new com.jme3.asset.TextureKey(p, false));
if (tex != null && tex.getImage() != null) {
int w = tex.getImage().getWidth();
int h = tex.getImage().getHeight();
if (w > 0 && h > 0) slotAspectRatios[s] = (float) w / h;
}
} catch (Exception e) {
log.debug("[GrassState] Aspect-Ratio nicht lesbar Slot {}: {}", s, e.getMessage());
}
}
}
@Override
@@ -228,8 +251,10 @@ public class GrassState extends BaseAppState
if (entry.getValue().isEmpty()) continue;
Material mat = getSlotMaterial(entry.getKey());
if (mat == null) continue;
Geometry geo = new Geometry("grass_" + idx + "_s" + entry.getKey(),
buildGrassMesh(entry.getValue()));
int slot = entry.getKey();
float ar = (slot < slotAspectRatios.length) ? slotAspectRatios[slot] : 1f;
Geometry geo = new Geometry("grass_" + idx + "_s" + slot,
buildGrassMesh(entry.getValue(), ar));
geo.setMaterial(mat);
node.attachChild(geo);
}
@@ -288,7 +313,7 @@ public class GrassState extends BaseAppState
// ── Mesh: Kreuz-Quad mit UV ───────────────────────────────────────────────
private static Mesh buildGrassMesh(List<float[]> blades) {
private static Mesh buildGrassMesh(List<float[]> blades, float ar) {
int n = blades.size();
FloatBuffer pos = BufferUtils.createFloatBuffer(n * 8 * 3);
FloatBuffer uv = BufferUtils.createFloatBuffer(n * 8 * 2);
@@ -298,7 +323,7 @@ public class GrassState extends BaseAppState
int vi = 0;
for (float[] blade : blades) {
float x = blade[0], y = blade[1], z = blade[2], h = blade[3];
float w = Math.max(0.05f, h * BLADE_WIDTH);
float w = Math.max(0.05f, h * ar * 0.5f);
pos.put(x-w).put(y ).put(z); uv.put(0).put(0); nrm.put(0).put(1).put(0);
pos.put(x+w).put(y ).put(z); uv.put(1).put(0); nrm.put(0).put(1).put(0);