External Publication
Visit Post

Problem between tiles

jMonkeyEngine Hub May 15, 2026
Source

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

Loading comments...