From e670245d050e61a71e1bab72f3d463efd7656b37 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Sat, 25 Sep 2021 13:21:16 -0700 Subject: [PATCH] feat: add vertex attribute bindings for short and byte (#4906) --- .../assets/mesh/VertexGLAttributeTest.java | 36 +++++++++++++--- .../assets/mesh/VertexResourceTest.java | 10 +++-- .../assets/mesh/resource/GLAttributes.java | 28 ++++++++++--- .../mesh/resource/VertexByteAttribute.java | 24 +++++++++++ .../resource/VertexByteAttributeBinding.java | 41 +++++++++++++++++++ .../mesh/resource/VertexResourceBuilder.java | 13 ++++++ .../mesh/resource/VertexShortAttribute.java | 24 +++++++++++ .../resource/VertexShortAttributeBinding.java | 41 +++++++++++++++++++ .../rendering/primitives/ChunkMesh.java | 6 +-- .../world/block/shapes/BlockMeshPart.java | 4 +- 10 files changed, 206 insertions(+), 21 deletions(-) create mode 100644 engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttribute.java create mode 100644 engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttributeBinding.java create mode 100644 engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttribute.java create mode 100644 engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttributeBinding.java diff --git a/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexGLAttributeTest.java b/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexGLAttributeTest.java index 5afa46b1ff1..4c30b9a1ca7 100644 --- a/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexGLAttributeTest.java +++ b/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexGLAttributeTest.java @@ -12,10 +12,12 @@ import org.junit.Test; import org.terasology.engine.rendering.assets.mesh.resource.GLAttributes; import org.terasology.engine.rendering.assets.mesh.resource.VertexAttributeBinding; +import org.terasology.engine.rendering.assets.mesh.resource.VertexByteAttributeBinding; import org.terasology.engine.rendering.assets.mesh.resource.VertexFloatAttributeBinding; import org.terasology.engine.rendering.assets.mesh.resource.VertexIntegerAttributeBinding; import org.terasology.engine.rendering.assets.mesh.resource.VertexResource; import org.terasology.engine.rendering.assets.mesh.resource.VertexResourceBuilder; +import org.terasology.engine.rendering.assets.mesh.resource.VertexShortAttributeBinding; import org.terasology.nui.Color; import org.terasology.nui.Colorc; @@ -74,13 +76,13 @@ public void testIntBinding() { @Test public void testByteBinding() { VertexResourceBuilder builder = new VertexResourceBuilder(); - VertexIntegerAttributeBinding a1 = builder.add(0, GLAttributes.BYTE_1_VERTEX_ATTRIBUTE); + VertexByteAttributeBinding a1 = builder.add(0, GLAttributes.BYTE_1_VERTEX_ATTRIBUTE); VertexResource resource = builder.build(); - a1.put(10); - a1.put(150); - a1.put(300); - a1.put(100); + a1.put((byte) 10); + a1.put((byte) 150); + a1.put((byte) 100); + a1.put((byte) 100); assertEquals(4, a1.getPosition()); resource.writeBuffer(buffer -> { @@ -88,11 +90,33 @@ public void testByteBinding() { assertEquals(10, Byte.toUnsignedInt(buffer.get(Byte.BYTES * 0))); assertEquals(150, Byte.toUnsignedInt(buffer.get(Byte.BYTES * 1))); - assertEquals(255, Byte.toUnsignedInt(buffer.get(Byte.BYTES * 2))); + assertEquals(100, Byte.toUnsignedInt(buffer.get(Byte.BYTES * 2))); assertEquals(100, Byte.toUnsignedInt(buffer.get(Byte.BYTES * 3))); }); } + @Test + public void testShortBinding() { + VertexResourceBuilder builder = new VertexResourceBuilder(); + VertexShortAttributeBinding a1 = builder.add(0, GLAttributes.SHORT_1_VERTEX_ATTRIBUTE); + VertexResource resource = builder.build(); + + a1.put((short) 10); + a1.put((short) 150); + a1.put((short) 100); + a1.put((short) 100); + + assertEquals(4, a1.getPosition()); + resource.writeBuffer(buffer -> { + assertEquals(4 * Short.BYTES, buffer.limit()); + + assertEquals(10, Short.toUnsignedInt(buffer.getShort(Short.BYTES * 0))); + assertEquals(150, Short.toUnsignedInt(buffer.getShort(Short.BYTES * 1))); + assertEquals(100, Short.toUnsignedInt(buffer.getShort(Short.BYTES * 2))); + assertEquals(100, Short.toUnsignedInt(buffer.getShort(Short.BYTES * 3))); + }); + } + @Test public void testVector3fBinding() { VertexResourceBuilder builder = new VertexResourceBuilder(); diff --git a/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexResourceTest.java b/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexResourceTest.java index 83179a9ed19..8ee4bc35bba 100644 --- a/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexResourceTest.java +++ b/engine-tests/src/test/java/org/terasology/engine/rendering/assets/mesh/VertexResourceTest.java @@ -3,11 +3,13 @@ package org.terasology.engine.rendering.assets.mesh; +import com.google.common.primitives.UnsignedBytes; import org.joml.Vector3f; import org.joml.Vector3fc; import org.junit.Test; import org.terasology.engine.rendering.assets.mesh.resource.GLAttributes; import org.terasology.engine.rendering.assets.mesh.resource.VertexAttributeBinding; +import org.terasology.engine.rendering.assets.mesh.resource.VertexByteAttributeBinding; import org.terasology.engine.rendering.assets.mesh.resource.VertexIntegerAttributeBinding; import org.terasology.engine.rendering.assets.mesh.resource.VertexResource; import org.terasology.engine.rendering.assets.mesh.resource.VertexResourceBuilder; @@ -53,7 +55,7 @@ public void testReserveVertexResource() { public void testAllocation() { VertexResourceBuilder builder = new VertexResourceBuilder(); VertexAttributeBinding a1 = builder.add(0, GLAttributes.VECTOR_3_F_VERTEX_ATTRIBUTE); - VertexIntegerAttributeBinding a2 = builder.add(0, GLAttributes.BYTE_1_VERTEX_ATTRIBUTE); + VertexByteAttributeBinding a2 = builder.add(0, GLAttributes.BYTE_1_VERTEX_ATTRIBUTE); VertexResource resource = builder.build(); a1.allocate(10); int stride = (Float.BYTES * 3) + Byte.BYTES; @@ -67,12 +69,12 @@ public void testAllocation() { public void testInterleave() { VertexResourceBuilder builder = new VertexResourceBuilder(); VertexAttributeBinding a1 = builder.add(0, GLAttributes.VECTOR_3_F_VERTEX_ATTRIBUTE); - VertexIntegerAttributeBinding a2 = builder.add(0, GLAttributes.BYTE_1_VERTEX_ATTRIBUTE); + VertexByteAttributeBinding a2 = builder.add(0, GLAttributes.BYTE_1_VERTEX_ATTRIBUTE); VertexResource resource = builder.build(); a1.put(new Vector3f(10, 0, -4)); - a2.put(2); - a2.put(10); + a2.put(UnsignedBytes.checkedCast(2)); + a2.put(UnsignedBytes.checkedCast(10)); assertEquals(2, a2.getPosition()); assertEquals(1, a1.getPosition()); diff --git a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/GLAttributes.java b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/GLAttributes.java index df80263161d..2f563dcd471 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/GLAttributes.java +++ b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/GLAttributes.java @@ -3,7 +3,6 @@ package org.terasology.engine.rendering.assets.mesh.resource; -import org.joml.Math; import org.joml.Vector2f; import org.joml.Vector2fc; import org.joml.Vector3f; @@ -55,18 +54,35 @@ public int read(int vertIdx, int offset, VertexResource resource) { } }, TypeMapping.ATTR_INT, 1); - public static final VertexIntegerAttribute BYTE_1_VERTEX_ATTRIBUTE = - new VertexIntegerAttribute(new VertexIntegerAttribute.AttributeConfiguration() { + public static final VertexShortAttribute SHORT_1_VERTEX_ATTRIBUTE = + new VertexShortAttribute(new VertexShortAttribute.AttributeConfiguration() { + @Override + public void write(short value, int vertIdx, int offset, VertexResource resource) { + int bufferStart = vertIdx * resource.inStride() + offset; + ByteBuffer buffer = resource.buffer(); + buffer.putShort(bufferStart, value); + } + + @Override + public short read(int vertIdx, int offset, VertexResource resource) { + int bufferStart = vertIdx * resource.inStride() + offset; + ByteBuffer buffer = resource.buffer(); + return buffer.getShort(bufferStart); + } + }, TypeMapping.ATTR_SHORT, 1); + + public static final VertexByteAttribute BYTE_1_VERTEX_ATTRIBUTE = + new VertexByteAttribute(new VertexByteAttribute.AttributeConfiguration() { @Override - public void write(int value, int vertIdx, int offset, VertexResource resource) { + public void write(byte value, int vertIdx, int offset, VertexResource resource) { int bufferStart = vertIdx * resource.inStride() + offset; ByteBuffer buffer = resource.buffer(); - buffer.put(bufferStart, ((byte) Math.clamp(0, 255, value))); + buffer.put(bufferStart, value); } @Override - public int read(int vertIdx, int offset, VertexResource resource) { + public byte read(int vertIdx, int offset, VertexResource resource) { int bufferStart = vertIdx * resource.inStride() + offset; ByteBuffer buffer = resource.buffer(); return buffer.get(bufferStart); diff --git a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttribute.java b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttribute.java new file mode 100644 index 00000000000..036cc072316 --- /dev/null +++ b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttribute.java @@ -0,0 +1,24 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.engine.rendering.assets.mesh.resource; + +public class VertexByteAttribute extends BaseVertexAttribute { + public final VertexByteAttribute.AttributeConfiguration configuration; + + /** + * @param mapping maps a primitive to a given supported type. + * @param count the number elements that is described by the target + */ + protected VertexByteAttribute(VertexByteAttribute.AttributeConfiguration attributeConfiguration, + TypeMapping mapping, int count) { + super(mapping, count); + this.configuration = attributeConfiguration; + } + + public interface AttributeConfiguration { + void write(byte value, int vertIdx, int offset, VertexResource resource); + + byte read(int vertIdx, int offset, VertexResource resource); + } +} diff --git a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttributeBinding.java b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttributeBinding.java new file mode 100644 index 00000000000..ac30665ff35 --- /dev/null +++ b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexByteAttributeBinding.java @@ -0,0 +1,41 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.engine.rendering.assets.mesh.resource; + +public class VertexByteAttributeBinding extends VertexBinding { + + private final VertexByteAttribute attribute; + + public VertexByteAttributeBinding(VertexResource resource, int offset, VertexByteAttribute attribute) { + super(resource, offset); + this.attribute = attribute; + } + + public int elements() { + return getResource().elements(); + } + + @Override + public void reserve(int vertCount) { + resource.reserveElements(vertCount); + } + + @Override + public void allocate(int elements) { + resource.allocateElements(elements); + resource.mark(); + } + + public void put(byte value) { + resource.ensureElements(this.vertexIndex + 1); + attribute.configuration.write(value, this.vertexIndex, this.offset, resource); + this.vertexIndex++; + this.resource.mark(); + } + + public void set(int index, byte value) { + attribute.configuration.write(value, index, this.offset, resource); + this.resource.mark(); + } +} diff --git a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexResourceBuilder.java b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexResourceBuilder.java index 11f70d6af44..5be9864e04b 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexResourceBuilder.java +++ b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexResourceBuilder.java @@ -46,6 +46,19 @@ public VertexFloatAttributeBinding add(int location, VertexFloatAttribute attrib return result; } + public VertexByteAttributeBinding add(int location, VertexByteAttribute attribute) { + VertexByteAttributeBinding result = new VertexByteAttributeBinding(resource, inStride, attribute); + this.definitions.add(new VertexResource.VertexDefinition(location, inStride, attribute)); + inStride += attribute.mapping.size * attribute.count; + return result; + } + + public VertexShortAttributeBinding add(int location, VertexShortAttribute attribute) { + VertexShortAttributeBinding result = new VertexShortAttributeBinding(resource, inStride, attribute); + this.definitions.add(new VertexResource.VertexDefinition(location, inStride, attribute)); + inStride += attribute.mapping.size * attribute.count; + return result; + } public VertexResource build() { resource.setDefinitions(definitions.toArray(new VertexResource.VertexDefinition[]{})); diff --git a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttribute.java b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttribute.java new file mode 100644 index 00000000000..58cf6f181d5 --- /dev/null +++ b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttribute.java @@ -0,0 +1,24 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.engine.rendering.assets.mesh.resource; + +public class VertexShortAttribute extends BaseVertexAttribute { + public final VertexShortAttribute.AttributeConfiguration configuration; + + /** + * @param mapping maps a primitive to a given supported type. + * @param count the number elements that is described by the target + */ + protected VertexShortAttribute(VertexShortAttribute.AttributeConfiguration attributeConfiguration, + TypeMapping mapping, int count) { + super(mapping, count); + this.configuration = attributeConfiguration; + } + + public interface AttributeConfiguration { + void write(short value, int vertIdx, int offset, VertexResource resource); + + short read(int vertIdx, int offset, VertexResource resource); + } +} diff --git a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttributeBinding.java b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttributeBinding.java new file mode 100644 index 00000000000..c3a19ef346c --- /dev/null +++ b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/VertexShortAttributeBinding.java @@ -0,0 +1,41 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.engine.rendering.assets.mesh.resource; + +public class VertexShortAttributeBinding extends VertexBinding { + + private final VertexShortAttribute attribute; + + public VertexShortAttributeBinding(VertexResource resource, int offset, VertexShortAttribute attribute) { + super(resource, offset); + this.attribute = attribute; + } + + public int elements() { + return getResource().elements(); + } + + @Override + public void reserve(int vertCount) { + resource.reserveElements(vertCount); + } + + @Override + public void allocate(int elements) { + resource.allocateElements(elements); + resource.mark(); + } + + public void put(short value) { + resource.ensureElements(this.vertexIndex + 1); + attribute.configuration.write(value, this.vertexIndex, this.offset, resource); + this.vertexIndex++; + this.resource.mark(); + } + + public void set(int index, short value) { + attribute.configuration.write(value, index, this.offset, resource); + this.resource.mark(); + } +} diff --git a/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkMesh.java b/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkMesh.java index 6ee6720f480..6ce759633e7 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkMesh.java +++ b/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkMesh.java @@ -11,8 +11,8 @@ import org.terasology.engine.rendering.assets.mesh.resource.GLAttributes; import org.terasology.engine.rendering.assets.mesh.resource.IndexResource; import org.terasology.engine.rendering.assets.mesh.resource.VertexAttributeBinding; +import org.terasology.engine.rendering.assets.mesh.resource.VertexByteAttributeBinding; import org.terasology.engine.rendering.assets.mesh.resource.VertexFloatAttributeBinding; -import org.terasology.engine.rendering.assets.mesh.resource.VertexIntegerAttributeBinding; import org.terasology.engine.rendering.assets.mesh.resource.VertexResource; import org.terasology.engine.rendering.assets.mesh.resource.VertexResourceBuilder; import org.terasology.gestalt.module.sandbox.API; @@ -321,8 +321,8 @@ public static class VertexElements { public final VertexAttributeBinding color; - public final VertexIntegerAttributeBinding flags; - public final VertexIntegerAttributeBinding frames; + public final VertexByteAttributeBinding flags; + public final VertexByteAttributeBinding frames; public final VertexFloatAttributeBinding sunlight; // this could be changed to a single byte public final VertexFloatAttributeBinding blockLight; // this could be changed to a single byte diff --git a/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java b/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java index 516a547a7fc..1ff1bba9632 100644 --- a/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java +++ b/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java @@ -94,8 +94,8 @@ public void appendTo(ChunkMesh chunk, ChunkView chunkView, int offsetX, int offs elements.color.put(colorOffset); elements.position.put(pos.set(vertices[vIdx]).add(offsetX, offsetY, offsetZ)); elements.normals.put(normals[vIdx]); - elements.flags.put(flags.getValue()); - elements.frames.put(texFrames - 1); + elements.flags.put((byte) (flags.getValue())); + elements.frames.put((byte) (texFrames - 1)); float[] lightingData = calcLightingValuesForVertexPos(chunkView, vertices[vIdx].add(offsetX, offsetY, offsetZ, new Vector3f()), normals[vIdx]); elements.sunlight.put(lightingData[0]);