Weiter gebastelt
This commit is contained in:
@@ -1,16 +1,25 @@
|
||||
package de.blight.game.animation;
|
||||
|
||||
import com.jme3.anim.*;
|
||||
import com.jme3.math.FastMath;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.control.Control;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import com.jme3.anim.AnimClip;
|
||||
import com.jme3.anim.AnimComposer;
|
||||
import com.jme3.anim.AnimTrack;
|
||||
import com.jme3.anim.Armature;
|
||||
import com.jme3.anim.Joint;
|
||||
import com.jme3.anim.SkinningControl;
|
||||
import com.jme3.anim.TransformTrack;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.control.Control;
|
||||
|
||||
/**
|
||||
* Model-space retargeting with correct parent-chain propagation.
|
||||
@@ -406,7 +415,6 @@ public final class RetargetingSystem {
|
||||
return findControl(s, SkinningControl.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends Control> T findControl(Spatial s, Class<T> type) {
|
||||
T c = s.getControl(type);
|
||||
if (c != null) return c;
|
||||
|
||||
@@ -108,6 +108,12 @@ public class WorldScene extends BaseAppState {
|
||||
|
||||
@Override
|
||||
protected void onEnable() {
|
||||
try {
|
||||
assetManager.registerLocator(
|
||||
AnimationLibrary.findAssetRoot().toAbsolutePath().toString(),
|
||||
com.jme3.asset.plugins.FileLocator.class);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
BlightGame.status("Baue Beleuchtung und Himmel...");
|
||||
buildLighting();
|
||||
|
||||
@@ -529,6 +535,7 @@ public class WorldScene extends BaseAppState {
|
||||
String[] mapTex = map.terrainTextures;
|
||||
String[] matParams = {"DiffuseMap","DiffuseMap_1","DiffuseMap_2","DiffuseMap_3"};
|
||||
String[] scaleP = {"DiffuseMap_0_scale","DiffuseMap_1_scale","DiffuseMap_2_scale","DiffuseMap_3_scale"};
|
||||
String[] nmParams = {"NormalMap","NormalMap_1","NormalMap_2","NormalMap_3"};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
String path = (mapTex[i] != null && !mapTex[i].isEmpty()) ? mapTex[i] : DEF_TEX[i];
|
||||
if (path == null || path.isEmpty()) continue;
|
||||
@@ -536,6 +543,18 @@ public class WorldScene extends BaseAppState {
|
||||
tex.setWrap(Texture.WrapMode.Repeat);
|
||||
mat.setTexture(matParams[i], tex);
|
||||
mat.setFloat(scaleP[i], 512f);
|
||||
String nmp = map.terrainNormalMaps[i];
|
||||
System.out.println("[WorldScene] Slot " + i + " NormalMap: '" + nmp + "'");
|
||||
if (nmp != null && !nmp.isEmpty()) {
|
||||
try {
|
||||
Texture nm = assetManager.loadTexture(nmp);
|
||||
nm.setWrap(Texture.WrapMode.Repeat);
|
||||
mat.setTexture(nmParams[i], nm);
|
||||
System.out.println("[WorldScene] Slot " + i + " NormalMap geladen OK");
|
||||
} catch (Exception e) {
|
||||
System.err.println("[WorldScene] NormalMap nicht ladbar: " + nmp + " – " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ältere Maps haben splatR=0 → Gras (Slot 0) wäre unsichtbar; auf 255 setzen.
|
||||
|
||||
@@ -282,6 +282,7 @@ public class TerrainChunkState extends BaseAppState {
|
||||
|
||||
float[] positions = new float[vertCount * 3];
|
||||
float[] normals = new float[vertCount * 3];
|
||||
float[] tangents = new float[vertCount * 4];
|
||||
float[] texCoords = new float[vertCount * 2];
|
||||
int[] indices = new int[indexCount];
|
||||
|
||||
@@ -307,12 +308,23 @@ public class TerrainChunkState extends BaseAppState {
|
||||
if (nLen > 1e-6f) { nx /= nLen; ny /= nLen; nz /= nLen; }
|
||||
normals[pi] = nx; normals[pi+1] = ny; normals[pi+2] = nz;
|
||||
|
||||
// Welt-Raum UV (0–1 über 4096 m) für globale Splat-Map
|
||||
// Tangente: Projektion der +X-Achse auf die Oberfläche (Gram-Schmidt)
|
||||
// U wächst mit worldX → Tangente zeigt in +X-Richtung
|
||||
float dotX = nx; // dot((1,0,0), N)
|
||||
float tx = 1f - dotX * nx;
|
||||
float ty = -dotX * ny;
|
||||
float tz = -dotX * nz;
|
||||
float tLen = (float) Math.sqrt(tx*tx + ty*ty + tz*tz);
|
||||
if (tLen > 1e-6f) { tx /= tLen; ty /= tLen; tz /= tLen; }
|
||||
int gi = vi * 4;
|
||||
tangents[gi] = tx; tangents[gi+1] = ty; tangents[gi+2] = tz; tangents[gi+3] = 1f;
|
||||
|
||||
// Welt-Raum UV für Splat-Map: JME3-TerrainQuad-Konvention V=0 → worldZ=+2048
|
||||
float worldX = chunkCX + lx;
|
||||
float worldZ = chunkCZ + lz;
|
||||
int ti = vi * 2;
|
||||
texCoords[ti] = (worldX + 2048f) / 4096f;
|
||||
texCoords[ti+1] = (worldZ + 2048f) / 4096f;
|
||||
texCoords[ti+1] = 1f - (worldZ + 2048f) / 4096f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,6 +343,7 @@ public class TerrainChunkState extends BaseAppState {
|
||||
Mesh mesh = new Mesh();
|
||||
mesh.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(positions));
|
||||
mesh.setBuffer(VertexBuffer.Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
|
||||
mesh.setBuffer(VertexBuffer.Type.Tangent, 4, BufferUtils.createFloatBuffer(tangents));
|
||||
mesh.setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoords));
|
||||
mesh.setBuffer(VertexBuffer.Type.Index, 3, BufferUtils.createIntBuffer(indices));
|
||||
mesh.updateBound();
|
||||
|
||||
@@ -11,8 +11,6 @@ import com.jme3.input.controls.ActionListener;
|
||||
import com.jme3.input.controls.KeyTrigger;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.math.FastMath;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Node;
|
||||
@@ -64,9 +62,6 @@ public class WorldItemsState extends BaseAppState {
|
||||
private final List<Spatial> visuals = new ArrayList<>();
|
||||
private final Map<String, Item> itemDefs = new HashMap<>();
|
||||
|
||||
private final Quaternion rotQuat = new Quaternion();
|
||||
private float rotAccum = 0f;
|
||||
|
||||
public WorldItemsState(KeyBindings keyBindings, CharacterControl physicsChar,
|
||||
MainCharacter mainCharacter, PlayerInputControl playerInput) {
|
||||
this.keyBindings = keyBindings;
|
||||
@@ -136,12 +131,7 @@ public class WorldItemsState extends BaseAppState {
|
||||
protected void cleanup(Application app) {}
|
||||
|
||||
@Override
|
||||
public void update(float tpf) {
|
||||
if (visuals.isEmpty()) return;
|
||||
rotAccum += tpf * 60f;
|
||||
rotQuat.fromAngles(0f, rotAccum * FastMath.DEG_TO_RAD, 0f);
|
||||
for (Spatial s : visuals) s.setLocalRotation(rotQuat);
|
||||
}
|
||||
public void update(float tpf) {}
|
||||
|
||||
// ── Interaktion ───────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user