mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-22 18:45:21 +01:00
Switch face-sorting to merge-sort
This commit is contained in:
parent
63a003b13e
commit
d1ab1c6ca0
@ -29,14 +29,12 @@
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import de.bluecolored.bluemap.core.util.InstancePool;
|
||||
import de.bluecolored.bluemap.core.util.MergeSort;
|
||||
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
||||
import de.bluecolored.bluemap.core.util.math.MatrixM4f;
|
||||
import de.bluecolored.bluemap.core.util.math.VectorM3f;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -64,7 +62,7 @@ public class HiresTileModel {
|
||||
private double[] position;
|
||||
private float[] color, uv, ao;
|
||||
private byte[] sunlight, blocklight;
|
||||
private int[] materialIndex;
|
||||
private int[] materialIndex, materialIndexSort, materialIndexSortSupport;
|
||||
|
||||
public HiresTileModel(int initialCapacity) {
|
||||
if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity is negative");
|
||||
@ -388,6 +386,9 @@ private void setCapacity(int capacity) {
|
||||
sunlight = new byte [capacity * FI_SUNLIGHT];
|
||||
blocklight = new byte [capacity * FI_BLOCKLIGHT];
|
||||
materialIndex = new int [capacity * FI_MATERIAL_INDEX];
|
||||
|
||||
materialIndexSort = new int[materialIndex.length];
|
||||
materialIndexSortSupport = new int [materialIndex.length];
|
||||
}
|
||||
|
||||
public void writeBufferGeometryJson(OutputStream out) throws IOException {
|
||||
@ -396,6 +397,8 @@ public void writeBufferGeometryJson(OutputStream out) throws IOException {
|
||||
Gson gson = new GsonBuilder().create();
|
||||
JsonWriter json = gson.newJsonWriter(new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8), 81920));
|
||||
|
||||
Writer w = null;
|
||||
|
||||
json.beginObject(); // main-object
|
||||
json.name("tileGeometry").beginObject(); // tile-geometry-object
|
||||
|
||||
@ -583,20 +586,20 @@ private void writeMaterialGroups(JsonWriter json) throws IOException {
|
||||
material = materialIndex[i];
|
||||
|
||||
if (material != lastMaterial) {
|
||||
json.name("count").value((i - groupStart) * 3);
|
||||
json.name("count").value((i - groupStart) * 3L);
|
||||
json.endObject();
|
||||
|
||||
groupStart = i;
|
||||
|
||||
json.beginObject();
|
||||
json.name("materialIndex").value(material);
|
||||
json.name("start").value(groupStart * 3);
|
||||
json.name("start").value(groupStart * 3L);
|
||||
}
|
||||
|
||||
lastMaterial = material;
|
||||
}
|
||||
|
||||
json.name("count").value((miSize - groupStart) * 3);
|
||||
json.name("count").value((miSize - groupStart) * 3L);
|
||||
json.endObject();
|
||||
|
||||
}
|
||||
@ -611,32 +614,28 @@ private void writeRounded(JsonWriter json, double value) throws IOException {
|
||||
else json.value(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does an optimized selection sort to sort all faces based on their material-index.
|
||||
* A selection sort is chosen, because it requires the least amount of swaps, which seem (untested) to be the most expensive operation here
|
||||
*/
|
||||
private void sort() {
|
||||
if (size <= 1) return; // nothing to sort
|
||||
|
||||
int prev = Integer.MIN_VALUE, min, minIndex, i, j;
|
||||
for (i = 0; i < size - 1; i++){
|
||||
minIndex = i;
|
||||
min = materialIndex[minIndex];
|
||||
if (min <= prev) continue; // shortcut
|
||||
|
||||
for (j = i + 1; j < size; j++){
|
||||
if (materialIndex[j] < min){
|
||||
minIndex = j;
|
||||
min = materialIndex[minIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if (minIndex != i) {
|
||||
swap(minIndex, i);
|
||||
}
|
||||
|
||||
prev = min;
|
||||
// initialize material-index-sort
|
||||
for (int i = 0; i < size; i++) {
|
||||
materialIndexSort[i] = i;
|
||||
materialIndexSortSupport[i] = i;
|
||||
}
|
||||
|
||||
// sort
|
||||
MergeSort.mergeSortInt(materialIndexSort, 0, size, this::compareMaterialIndex, materialIndexSortSupport);
|
||||
|
||||
// move
|
||||
for (int i = 0; i < size; i++) {
|
||||
while (materialIndexSort[i] != i) {
|
||||
swap(i, materialIndexSort[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int compareMaterialIndex(int i1, int i2) {
|
||||
return Integer.compare(materialIndex[i1], materialIndex[i2]);
|
||||
}
|
||||
|
||||
private void swap(int face1, int face2) {
|
||||
@ -695,6 +694,11 @@ private void swap(int face1, int face2) {
|
||||
vi = materialIndex[face1];
|
||||
materialIndex[face1] = materialIndex[face2];
|
||||
materialIndex[face2] = vi;
|
||||
|
||||
//swap material-index-sort (assuming FI_MATERIAL_INDEX = 1)
|
||||
vi = materialIndexSort[face1];
|
||||
materialIndexSort[face1] = materialIndexSort[face2];
|
||||
materialIndexSort[face2] = vi;
|
||||
}
|
||||
|
||||
private static void calculateSurfaceNormal(
|
||||
|
@ -0,0 +1,15 @@
|
||||
package de.bluecolored.bluemap.core.util;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IntComparator extends Comparator<Integer> {
|
||||
|
||||
int compare(int o1, int o2);
|
||||
|
||||
@Override
|
||||
default int compare(Integer o1, Integer o2) {
|
||||
return compare(o1.intValue(), o2.intValue());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package de.bluecolored.bluemap.core.util;
|
||||
|
||||
public class MergeSort {
|
||||
|
||||
/*
|
||||
* Adapted from: https://github.com/vigna/fastutil
|
||||
*/
|
||||
public static void mergeSortInt(final int[] a, final int from, final int to, IntComparator comp, int[] supp) {
|
||||
int len = to - from;
|
||||
|
||||
if (len < 16) {
|
||||
insertionSortInt(a, from, to, comp);
|
||||
return;
|
||||
}
|
||||
if (supp == null) supp = java.util.Arrays.copyOf(a, to);
|
||||
|
||||
final int mid = (from + to) >>> 1;
|
||||
mergeSortInt(supp, from, mid, comp, a);
|
||||
mergeSortInt(supp, mid, to, comp, a);
|
||||
|
||||
if (comp.compare(supp[mid - 1], supp[mid]) <= 0) {
|
||||
System.arraycopy(supp, from, a, from, len);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = from, p = from, q = mid; i < to; i++) {
|
||||
if (q >= to || p < mid && comp.compare(supp[p], supp[q]) <= 0) a[i] = supp[p++];
|
||||
else a[i] = supp[q++];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adapted from: https://github.com/vigna/fastutil
|
||||
*/
|
||||
private static void insertionSortInt(final int[] a, final int from, final int to, final IntComparator comp) {
|
||||
for (int i = from; ++i < to; ) {
|
||||
int t = a[i], j = i;
|
||||
for (int u = a[j - 1]; comp.compare(t, u) < 0; u = a[--j - 1]) {
|
||||
a[j] = u;
|
||||
if (from == j - 1) {
|
||||
--j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user