Gras (Textur) Pinsel Bugs behoben
This commit is contained in:
@@ -147,6 +147,33 @@ public class PlacedObjectState extends BaseAppState {
|
|||||||
grassNode = new Node("grassNode");
|
grassNode = new Node("grassNode");
|
||||||
((SimpleApplication) app).getRootNode().attachChild(grassNode);
|
((SimpleApplication) app).getRootNode().attachChild(grassNode);
|
||||||
applyAllSlotMaterials();
|
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
|
@Override
|
||||||
|
|||||||
@@ -36,18 +36,18 @@ public class GrassState extends BaseAppState
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(GrassState.class);
|
private static final Logger log = LoggerFactory.getLogger(GrassState.class);
|
||||||
|
|
||||||
private static final int TERRAIN_HALF = 2048;
|
private static final int CHUNK_SIZE = de.blight.common.ChunkTerrainIO.CHUNK_SIZE; // 128
|
||||||
private static final int CHUNK_SIZE = 128;
|
private static final int TERRAIN_HALF = de.blight.common.ChunkTerrainIO.WORLD_SIZE / 2; // 1024
|
||||||
private static final int CHUNKS_PER_AXIS = (TERRAIN_HALF * 2) / CHUNK_SIZE; // 32
|
private static final int CHUNKS_PER_AXIS = de.blight.common.ChunkTerrainIO.CHUNKS_PER_AXIS; // 16
|
||||||
private static final int CHUNK_COUNT = CHUNKS_PER_AXIS * CHUNKS_PER_AXIS; // 1024
|
private static final int CHUNK_COUNT = de.blight.common.ChunkTerrainIO.CHUNK_COUNT; // 256
|
||||||
private static final int BLADES_PER_TUFT = 4;
|
private static final int BLADES_PER_TUFT = 4;
|
||||||
private static final float TUFT_SPREAD = 0.5f;
|
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 static final int INIT_PER_FRAME = 4;
|
||||||
|
|
||||||
private final TerrainChunkState terrainChunkState;
|
private final TerrainChunkState terrainChunkState;
|
||||||
|
|
||||||
private Node grassNode;
|
private Node grassNode;
|
||||||
|
private float[] slotAspectRatios = new float[8];
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
private final List<GrassTuft>[] chunkTufts = new List[CHUNK_COUNT];
|
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<>();
|
for (int i = 0; i < CHUNK_COUNT; i++) chunkTufts[i] = new ArrayList<>();
|
||||||
|
|
||||||
|
GrassTuftIO.GrassData data = null;
|
||||||
try {
|
try {
|
||||||
GrassTuftIO.GrassData data = GrassTuftIO.load();
|
data = GrassTuftIO.load();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
initSlotMaterials(app.getAssetManager(), data.slotPaths());
|
initSlotMaterials(app.getAssetManager(), data.slotPaths());
|
||||||
for (GrassTuft t : data.tufts()) {
|
for (GrassTuft t : data.tufts()) {
|
||||||
@@ -85,6 +86,28 @@ public class GrassState extends BaseAppState
|
|||||||
if (slotMaterials.isEmpty()) {
|
if (slotMaterials.isEmpty()) {
|
||||||
slotMaterials.put(0, buildGrassMat(app.getAssetManager(), ""));
|
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
|
@Override
|
||||||
@@ -228,8 +251,10 @@ public class GrassState extends BaseAppState
|
|||||||
if (entry.getValue().isEmpty()) continue;
|
if (entry.getValue().isEmpty()) continue;
|
||||||
Material mat = getSlotMaterial(entry.getKey());
|
Material mat = getSlotMaterial(entry.getKey());
|
||||||
if (mat == null) continue;
|
if (mat == null) continue;
|
||||||
Geometry geo = new Geometry("grass_" + idx + "_s" + entry.getKey(),
|
int slot = entry.getKey();
|
||||||
buildGrassMesh(entry.getValue()));
|
float ar = (slot < slotAspectRatios.length) ? slotAspectRatios[slot] : 1f;
|
||||||
|
Geometry geo = new Geometry("grass_" + idx + "_s" + slot,
|
||||||
|
buildGrassMesh(entry.getValue(), ar));
|
||||||
geo.setMaterial(mat);
|
geo.setMaterial(mat);
|
||||||
node.attachChild(geo);
|
node.attachChild(geo);
|
||||||
}
|
}
|
||||||
@@ -288,7 +313,7 @@ public class GrassState extends BaseAppState
|
|||||||
|
|
||||||
// ── Mesh: Kreuz-Quad mit UV ───────────────────────────────────────────────
|
// ── 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();
|
int n = blades.size();
|
||||||
FloatBuffer pos = BufferUtils.createFloatBuffer(n * 8 * 3);
|
FloatBuffer pos = BufferUtils.createFloatBuffer(n * 8 * 3);
|
||||||
FloatBuffer uv = BufferUtils.createFloatBuffer(n * 8 * 2);
|
FloatBuffer uv = BufferUtils.createFloatBuffer(n * 8 * 2);
|
||||||
@@ -298,7 +323,7 @@ public class GrassState extends BaseAppState
|
|||||||
int vi = 0;
|
int vi = 0;
|
||||||
for (float[] blade : blades) {
|
for (float[] blade : blades) {
|
||||||
float x = blade[0], y = blade[1], z = blade[2], h = blade[3];
|
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(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);
|
pos.put(x+w).put(y ).put(z); uv.put(1).put(0); nrm.put(0).put(1).put(0);
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user