117 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package com.mojang.blaze3d.vertex;
 | |
| 
 | |
| import it.unimi.dsi.fastutil.ints.IntConsumer;
 | |
| import java.nio.ByteBuffer;
 | |
| import java.nio.FloatBuffer;
 | |
| import net.fabricmc.api.EnvType;
 | |
| import net.fabricmc.api.Environment;
 | |
| import org.apache.commons.lang3.mutable.MutableLong;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| import org.joml.Vector3f;
 | |
| import org.lwjgl.system.MemoryUtil;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| public class MeshData implements AutoCloseable {
 | |
| 	private final ByteBufferBuilder.Result vertexBuffer;
 | |
| 	@Nullable
 | |
| 	private ByteBufferBuilder.Result indexBuffer;
 | |
| 	private final MeshData.DrawState drawState;
 | |
| 
 | |
| 	public MeshData(ByteBufferBuilder.Result vertexBuffer, MeshData.DrawState drawState) {
 | |
| 		this.vertexBuffer = vertexBuffer;
 | |
| 		this.drawState = drawState;
 | |
| 	}
 | |
| 
 | |
| 	private static Vector3f[] unpackQuadCentroids(ByteBuffer byteBuffer, int vertexCount, VertexFormat format) {
 | |
| 		int i = format.getOffset(VertexFormatElement.POSITION);
 | |
| 		if (i == -1) {
 | |
| 			throw new IllegalArgumentException("Cannot identify quad centers with no position element");
 | |
| 		} else {
 | |
| 			FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
 | |
| 			int j = format.getVertexSize() / 4;
 | |
| 			int k = j * 4;
 | |
| 			int l = vertexCount / 4;
 | |
| 			Vector3f[] vector3fs = new Vector3f[l];
 | |
| 
 | |
| 			for (int m = 0; m < l; m++) {
 | |
| 				int n = m * k + i;
 | |
| 				int o = n + j * 2;
 | |
| 				float f = floatBuffer.get(n + 0);
 | |
| 				float g = floatBuffer.get(n + 1);
 | |
| 				float h = floatBuffer.get(n + 2);
 | |
| 				float p = floatBuffer.get(o + 0);
 | |
| 				float q = floatBuffer.get(o + 1);
 | |
| 				float r = floatBuffer.get(o + 2);
 | |
| 				vector3fs[m] = new Vector3f((f + p) / 2.0F, (g + q) / 2.0F, (h + r) / 2.0F);
 | |
| 			}
 | |
| 
 | |
| 			return vector3fs;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public ByteBuffer vertexBuffer() {
 | |
| 		return this.vertexBuffer.byteBuffer();
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	public ByteBuffer indexBuffer() {
 | |
| 		return this.indexBuffer != null ? this.indexBuffer.byteBuffer() : null;
 | |
| 	}
 | |
| 
 | |
| 	public MeshData.DrawState drawState() {
 | |
| 		return this.drawState;
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	public MeshData.SortState sortQuads(ByteBufferBuilder bufferBuilder, VertexSorting sorting) {
 | |
| 		if (this.drawState.mode() != VertexFormat.Mode.QUADS) {
 | |
| 			return null;
 | |
| 		} else {
 | |
| 			Vector3f[] vector3fs = unpackQuadCentroids(this.vertexBuffer.byteBuffer(), this.drawState.vertexCount(), this.drawState.format());
 | |
| 			MeshData.SortState sortState = new MeshData.SortState(vector3fs, this.drawState.indexType());
 | |
| 			this.indexBuffer = sortState.buildSortedIndexBuffer(bufferBuilder, sorting);
 | |
| 			return sortState;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public void close() {
 | |
| 		this.vertexBuffer.close();
 | |
| 		if (this.indexBuffer != null) {
 | |
| 			this.indexBuffer.close();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Environment(EnvType.CLIENT)
 | |
| 	public record DrawState(VertexFormat format, int vertexCount, int indexCount, VertexFormat.Mode mode, VertexFormat.IndexType indexType) {
 | |
| 	}
 | |
| 
 | |
| 	@Environment(EnvType.CLIENT)
 | |
| 	public record SortState(Vector3f[] centroids, VertexFormat.IndexType indexType) {
 | |
| 		@Nullable
 | |
| 		public ByteBufferBuilder.Result buildSortedIndexBuffer(ByteBufferBuilder bufferBuilder, VertexSorting sorting) {
 | |
| 			int[] is = sorting.sort(this.centroids);
 | |
| 			long l = bufferBuilder.reserve(is.length * 6 * this.indexType.bytes);
 | |
| 			IntConsumer intConsumer = this.indexWriter(l, this.indexType);
 | |
| 
 | |
| 			for (int i : is) {
 | |
| 				intConsumer.accept(i * 4 + 0);
 | |
| 				intConsumer.accept(i * 4 + 1);
 | |
| 				intConsumer.accept(i * 4 + 2);
 | |
| 				intConsumer.accept(i * 4 + 2);
 | |
| 				intConsumer.accept(i * 4 + 3);
 | |
| 				intConsumer.accept(i * 4 + 0);
 | |
| 			}
 | |
| 
 | |
| 			return bufferBuilder.build();
 | |
| 		}
 | |
| 
 | |
| 		private IntConsumer indexWriter(long index, VertexFormat.IndexType type) {
 | |
| 			MutableLong mutableLong = new MutableLong(index);
 | |
| 
 | |
| 			return switch (type) {
 | |
| 				case SHORT -> i -> MemoryUtil.memPutShort(mutableLong.getAndAdd(2L), (short)i);
 | |
| 				case INT -> i -> MemoryUtil.memPutInt(mutableLong.getAndAdd(4L), i);
 | |
| 			};
 | |
| 		}
 | |
| 	}
 | |
| }
 |