How to calculate Normals correctly?
To calculate the xyz coordinate of a square I use:
public static void writePositions(Tile tile) {
TileID tileId = tile.getTileId();
MemorySegment heightMap = HEIGHT_MAP_READER.getMapData(tileId);
CubePlane plane = GeoUtils.faceToPlane(tileId.face());
MeshBuffer buffer = tile.getBuffer();
float fixedValue = tile.getFixedValue();
FacePosition minCorner = tile.minCorner();
FacePosition maxCorner = tile.maxCorner();
calculateColRowArrays(minCorner.col(), maxCorner.col(), minCorner.row(), maxCorner.row());
writePlane(fixedValue, heightMap, plane, buffer.getPositionData());
}
There is a heigthmap reader because I want to add elevation or depth.
Example
each square as a max of 2 axis ,a min of 2 axis and a fixed value.
On a square top face y would be always the same.
Each square is divided into **63001** points.
I read a short value from the Memory Segment given by heigthMap reader and trans from it on a int, then on a float using SIMD. For each point I would use columnsBuffer and rowsBuffer.
Size of columnsBuffer and rowsBuffer is 251,
251^2 =63001.
For each point I normalize with
`ONE.div(len.sqrt())`
and add elevation/depth with
`mul(heightVecNormalized)`
private static void writePlane(float f, MemorySegment heightMap, CubePlane layout, MemorySegment buffer) {
FloatVector fixedVec = FloatVector.broadcast(FLOAT_VECTOR_SPECIES, f);
long offset = 0;
for (int i = 0; i < TILE_PIXELS; i++) {
float r = rowsBuffer.getAtIndex(JAVA_FLOAT, i);
FloatVector rowVec = FloatVector.broadcast(FLOAT_VECTOR_SPECIES, r);
for (int j = 0; j < TILE_PIXELS_BOUND; j += F_LENGTH) {
ShortVector heightVec = ShortVector.
fromMemorySegment(SHORT_SPECIES, heightMap, ((long) i * TILE_PIXELS + j) * Short.BYTES, LITTLE_ENDIAN);
FloatVector fv = (FloatVector) heightVec.convertShape(VectorOperators.ZERO_EXTEND_S2I, INT_SPECIES, 0)
.convertShape(VectorOperators.I2F, FLOAT_VECTOR_SPECIES, 0);
FloatVector heightVecNormalized = fv.fma(NORMALIZED_HEIGHT_SCALE_VECTOR, RADIUS_NORMALIZED_OFFSET_VECTOR);
FloatVector colVec = FloatVector.fromMemorySegment(FLOAT_VECTOR_SPECIES, columnsBuffer, (long) j * Float.BYTES, NATIVE_ORDER);
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);
FloatVector x = nx.rearrange(INTERLEAVE_PERMUTE_X);
FloatVector y = ny.rearrange(INTERLEAVE_PERMUTE_Y);
FloatVector z = nz.rearrange(INTERLEAVE_PERMUTE_Z);
FloatVector a0 = y.blend(x, INTERLEAVE_STAGE1_MASK);
FloatVector b0 = x.blend(z, INTERLEAVE_STAGE1_MASK);
FloatVector c0 = z.blend(y, INTERLEAVE_STAGE1_MASK);
FloatVector a = a0.blend(z, INTERLEAVE_STAGE2_MASK);
FloatVector b = b0.blend(y, INTERLEAVE_STAGE2_MASK);
FloatVector c = c0.blend(x, INTERLEAVE_STAGE2_MASK);
a.intoMemorySegment(buffer, offset, NATIVE_ORDER);
b.intoMemorySegment(buffer, offset + (long) F_LENGTH * Float.BYTES, NATIVE_ORDER);
c.intoMemorySegment(buffer, offset + 2L * F_LENGTH * Float.BYTES, NATIVE_ORDER);
offset += 3L * F_LENGTH * Float.BYTES;
}
long tailOffsetBytes = ((long) i * TILE_PIXELS + TILE_PIXELS_BOUND) * Short.BYTES;
for (int s = TILE_PIXELS_BOUND; s < TILE_PIXELS; s++) {
float c = columnsBuffer.getAtIndex(JAVA_FLOAT, s);
float wx = layout.sx(f, r, c);
float wy = layout.sy(f, r, c);
float wz = layout.sz(f, r, c);
float len = (float) Math.sqrt(Math.fma(wx, wx, Math.fma(wy, wy, wz * wz)));
float u = (float) Short.toUnsignedInt(heightMap.get(OF_SHORT, tailOffsetBytes));
float height = Math.fma(u, NORMALIZED_HEIGHT_SCALE, RADIUS_NORMALIZED_OFFSET);
float inv = 1f / len * height;
float nx = wx * inv;
float ny = wy * inv;
float nz = wz * inv;
VH_X.set(buffer, offset, nx);
VH_Y.set(buffer, offset, ny);
VH_Z.set(buffer, offset, nz);
offset += 3 * Float.BYTES;
tailOffsetBytes += Short.BYTES;
}
}
}