Problem between tiles
jMonkeyEngine Hub
May 15, 2026
Hello,
in my game I generate tiles and put those side by side. In the following picture is possible to see that there is a small section between those tiles. I would like to see some sugestions to resolve this problem.
package Terrain.buffer_utils.writers.position;
import Terrain.buffer_utils.HeightMapReader;
import Terrain.buffer_utils.MeshBuffer;
import Terrain.location.GeoEnum;
import Terrain.location.Position3D;
import Terrain.utils.Tile;
import Terrain.utils.TileID;
import com.config.WorldConfig;
import jdk.incubator.vector.*;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.nio.ByteOrder;
import static com.config.WorldConfig.TILE_PIXELS;
public class PositionWriter {
static final float PLANET_RADIUS = 6371000f;
static final float STEP = (WorldConfig.TILE_LENGTH / (TILE_PIXELS - 1));
static final VectorSpecies<Float> FLOAT_VECTOR_SPECIES = FloatVector.SPECIES_PREFERRED;
static final VectorSpecies<Integer> INT_SPECIES = IntVector.SPECIES_PREFERRED;
static final VectorSpecies<Short> SHORT_SPECIES = ShortVector.SPECIES_PREFERRED;
static final int TILE_PIXELS_BOUND_SHORT = SHORT_SPECIES.loopBound(WorldConfig.TILE_PIXELS);
static final int F_LENGTH = FLOAT_VECTOR_SPECIES.length();
static final int I_LENGTH = INT_SPECIES.length();
static final int S_LENGTH = SHORT_SPECIES.length();
static final int SHORT_VECTOR_LOOP_BOUND = TILE_PIXELS_BOUND_SHORT - S_LENGTH;
static final int INT_TO_FLOAT_GROUP_RATIO = INT_SPECIES.length() / F_LENGTH;
static final int SHORT_TO_INT_GROUP_RATIO = S_LENGTH / INT_SPECIES.length();
static final int TAIL_START_J = TILE_PIXELS_BOUND_SHORT;
static final int TAIL_LENGTH = TILE_PIXELS - TAIL_START_J;
static final FloatVector INDEX = FloatVector.fromArray(FLOAT_VECTOR_SPECIES, createIndex(), 0).mul(STEP);
static final float HEIGHT_SCALE = 3200.0f / (256f * 256f);
static final FloatVector ONE = FloatVector.broadcast(FLOAT_VECTOR_SPECIES, 1f);
static final float NORMALIZED_HEIGHT_SCALE = HEIGHT_SCALE / PLANET_RADIUS;
static final FloatVector NORMALIZED_HEIGHT_SCALE_VECTOR = FloatVector.broadcast(FLOAT_VECTOR_SPECIES, NORMALIZED_HEIGHT_SCALE);
static final float RADIUS_NORMALIZED_OFFSET = -200f / PLANET_RADIUS + 1f;
static final FloatVector RADIUS_NORMALIZED_OFFSET_VECTOR = FloatVector.broadcast(FLOAT_VECTOR_SPECIES, RADIUS_NORMALIZED_OFFSET);
private static final float[] meshData = new float[TILE_PIXELS * TILE_PIXELS * 3];
static final short[] shortArray = new short[TAIL_LENGTH];
static final float[] tmp = new float[F_LENGTH * 3];
private static final ValueLayout.OfShort OF_SHORT = ValueLayout.JAVA_SHORT_UNALIGNED.withOrder(ByteOrder.LITTLE_ENDIAN);
private static float[] createIndex() {
float[] a = new float[F_LENGTH];
for (int i = 0; i < F_LENGTH; i++)
a[i] = i;
return a;
}
public static void writePositions(Tile tile) {
TileID tileId = tile.getTileId();
GeoEnum face = tileId.face();
MeshBuffer buffer = tile.getBuffer();
MemorySegment heightMap = HeightMapReader.getInstance().getMapData(tileId);
CubePlane plane = switch (face) {
case TOP, BOTTOM -> CubePlane.HORIZONTAL;
case FRONT, BACK -> CubePlane.FRONTAL;
case LEFT, RIGHT -> CubePlane.PERFIL;
};
writePlane(tile.start(), heightMap, plane);
buffer.setPositionData(meshData);
}
static void writePlane(Position3D start, MemorySegment heightMap, CubePlane layout) {
float f = layout.fixedBase(start);
float rowBase = layout.rowBase(start);
float colBase = layout.colBase(start);
FloatVector fixedVec = FloatVector.broadcast(FLOAT_VECTOR_SPECIES, f);
FloatVector rowVec = FloatVector.broadcast(FLOAT_VECTOR_SPECIES, rowBase);
int offset = 0;
for (int i = 0; i < TILE_PIXELS; i++, rowVec = rowVec.add(STEP)) {
FloatVector colVec = INDEX.add(colBase);
for (int j = 0; j <= SHORT_VECTOR_LOOP_BOUND; j += S_LENGTH) {
ShortVector heightVec = ShortVector.fromMemorySegment(SHORT_SPECIES, heightMap, ((long) i * TILE_PIXELS + j) * Short.BYTES, ByteOrder.LITTLE_ENDIAN);
for (int k = 0; k < SHORT_TO_INT_GROUP_RATIO; k++) {
IntVector unsigned = (IntVector) heightVec.convertShape(VectorOperators.S2I, INT_SPECIES, k).lanewise(VectorOperators.AND, 0xFFFF);
for (int h = 0; h < INT_TO_FLOAT_GROUP_RATIO; h++, colVec = colVec.add(STEP * F_LENGTH)) {
FloatVector fv = (FloatVector) unsigned.convertShape(VectorOperators.I2F, FLOAT_VECTOR_SPECIES, h);
FloatVector heightVecNormalized = fv.fma(NORMALIZED_HEIGHT_SCALE_VECTOR, RADIUS_NORMALIZED_OFFSET_VECTOR);
FloatVector xVec = layout.wx(fixedVec, rowVec, colVec);
FloatVector yVec = layout.wy(fixedVec, rowVec, colVec);
FloatVector zVec = layout.wz(fixedVec, rowVec, colVec);
FloatVector len = xVec.fma(xVec, yVec.fma(yVec, zVec.mul(zVec)));
FloatVector invLen = ONE.div(len.sqrt()).mul(heightVecNormalized);
FloatVector nx = xVec.mul(invLen);
FloatVector ny = yVec.mul(invLen);
FloatVector nz = zVec.mul(invLen);
nx.intoArray(tmp, 0);
ny.intoArray(tmp, F_LENGTH);
nz.intoArray(tmp, F_LENGTH * 2);
for (int lane = 0; lane < F_LENGTH; lane++) {
meshData[offset++] = tmp[lane];
meshData[offset++] = tmp[lane + F_LENGTH];
meshData[offset++] = tmp[lane + F_LENGTH * 2];
}
}
}
}
long tailOffsetBytes = ((long) i * TILE_PIXELS + TAIL_START_J) * Short.BYTES;
MemorySegment.copy(heightMap, ValueLayout.JAVA_SHORT_UNALIGNED.withOrder(ByteOrder.LITTLE_ENDIAN), tailOffsetBytes, shortArray, 0, TAIL_LENGTH);
float r = rowBase + STEP * i;
for (int s = TAIL_START_J; s < TILE_PIXELS; s++) {
float c = colBase + STEP * s;
float len = (float) Math.sqrt(Math.fma(c, c, Math.fma(r, r, f * f)));
int u = Short.toUnsignedInt(shortArray[s - TAIL_START_J]);
float height =Math.fma(u, NORMALIZED_HEIGHT_SCALE, RADIUS_NORMALIZED_OFFSET);
float inv = height / len;
float wx = layout.sx(f, r, c);
float wy = layout.sy(f, r, c);
float wz = layout.sz(f, r, c);
meshData[offset++] = (wx * inv);
meshData[offset++] = (wy * inv);
meshData[offset++] = (wz * inv);
}
}
}
}
Thanks.
Discussion in the ATmosphere