mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 02:45:13 -04:00
fragmented array list
This commit is contained in:
parent
d3c96e6c6e
commit
6650712158
@ -29,8 +29,8 @@ open class ArmMesh(renderWindow: RenderWindow, primitiveType: PrimitiveTypes = r
|
||||
|
||||
|
||||
fun addVertex(position: FloatArray, uv: Vec2) {
|
||||
data.addAll(position)
|
||||
data.addAll(uv.array)
|
||||
data.add(position)
|
||||
data.add(uv.array)
|
||||
}
|
||||
|
||||
override fun addVertex(position: FloatArray, transformedUV: Vec2, transform: Float, textureShaderId: Float, flags: Float) {
|
||||
|
@ -30,7 +30,7 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.max
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.min
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.EMPTY
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.spaceSize
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
import de.bixilon.minosoft.util.collections.DirectList
|
||||
|
||||
abstract class Element(val guiRenderer: GUIRenderer, initialCacheSize: Int = 1000) : InputElement, DragTarget {
|
||||
var ignoreDisplaySize = false
|
||||
@ -168,7 +168,7 @@ abstract class Element(val guiRenderer: GUIRenderer, initialCacheSize: Int = 100
|
||||
cache.offset = Vec2i(offset)
|
||||
cache.options = options
|
||||
forceRender(offset, cache, options)
|
||||
if (cache.data !is DirectArrayFloatList) {
|
||||
if (cache.data !is DirectList) {
|
||||
// not raw mesh data
|
||||
cache.data.finish()
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.gui.gui
|
||||
import de.bixilon.kotlinglm.vec2.Vec2d
|
||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||
import de.bixilon.kutil.time.TimeUtil
|
||||
import de.bixilon.kutil.time.TimeUtil.millis
|
||||
import de.bixilon.minosoft.config.key.KeyCodes
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
@ -33,7 +34,7 @@ import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable
|
||||
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.FloatListUtil
|
||||
|
||||
open class GUIMeshElement<T : Element>(
|
||||
val element: T,
|
||||
@ -41,7 +42,7 @@ open class GUIMeshElement<T : Element>(
|
||||
override val guiRenderer: GUIRenderer = element.guiRenderer
|
||||
override val renderWindow: RenderWindow = guiRenderer.renderWindow
|
||||
private val clickCounter = MouseClickCounter()
|
||||
var mesh: GUIMesh = GUIMesh(renderWindow, guiRenderer.matrix, DirectArrayFloatList(1000))
|
||||
var mesh: GUIMesh = GUIMesh(renderWindow, guiRenderer.matrix, FloatListUtil.direct(1000))
|
||||
override val skipDraw: Boolean
|
||||
get() = if (element is BaseDrawable) element.skipDraw else false
|
||||
protected var lastRevision = 0L
|
||||
@ -144,7 +145,7 @@ open class GUIMeshElement<T : Element>(
|
||||
|
||||
val mouseAction = MouseActions[type] ?: return false
|
||||
|
||||
return element.onMouseAction(position, mouseButton, mouseAction, clickCounter.getClicks(mouseButton, mouseAction, position, TimeUtil.millis))
|
||||
return element.onMouseAction(position, mouseButton, mouseAction, clickCounter.getClicks(mouseButton, mouseAction, position, millis()))
|
||||
}
|
||||
|
||||
override fun onScroll(scrollOffset: Vec2d): Boolean {
|
||||
@ -167,7 +168,7 @@ open class GUIMeshElement<T : Element>(
|
||||
|
||||
val mouseAction = MouseActions[type] ?: return null
|
||||
|
||||
return element.onDragMouseAction(position, mouseButton, mouseAction, clickCounter.getClicks(mouseButton, mouseAction, position, TimeUtil.millis), dragged)
|
||||
return element.onDragMouseAction(position, mouseButton, mouseAction, clickCounter.getClicks(mouseButton, mouseAction, position, millis()), dragged)
|
||||
}
|
||||
|
||||
override fun onDragScroll(scrollOffset: Vec2d, dragged: Dragged): Element? {
|
||||
|
@ -27,7 +27,7 @@ import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.BufferedArrayFloatList
|
||||
|
||||
class CrosshairHUDElement(guiRenderer: GUIRenderer) : CustomHUDElement(guiRenderer) {
|
||||
private val profile = guiRenderer.connection.profiles.gui
|
||||
@ -90,7 +90,7 @@ class CrosshairHUDElement(guiRenderer: GUIRenderer) : CustomHUDElement(guiRender
|
||||
mesh?.unload()
|
||||
this.mesh = null
|
||||
|
||||
val mesh = GUIMesh(renderWindow, guiRenderer.matrix, DirectArrayFloatList(42))
|
||||
val mesh = GUIMesh(renderWindow, guiRenderer.matrix, BufferedArrayFloatList(42))
|
||||
val start = (guiRenderer.scaledSize - CROSSHAIR_SIZE) / 2
|
||||
mesh.addQuad(start, start + CROSSHAIR_SIZE, crosshairAtlasElement, crosshairProfile.color, null)
|
||||
|
||||
|
@ -24,12 +24,11 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.orthoTimes
|
||||
import de.bixilon.minosoft.util.collections.floats.AbstractFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
|
||||
class GUIMesh(
|
||||
renderWindow: RenderWindow,
|
||||
val matrix: Mat4,
|
||||
data: DirectArrayFloatList,
|
||||
data: AbstractFloatList,
|
||||
) : Mesh(renderWindow, GUIMeshStruct, initialCacheSize = 40000, clearOnLoad = false, data = data), GUIVertexConsumer {
|
||||
|
||||
override fun addVertex(position: Vec2t<*>, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?) {
|
||||
@ -37,7 +36,7 @@ class GUIMesh(
|
||||
}
|
||||
|
||||
override fun addCache(cache: GUIMeshCache) {
|
||||
data.addAll(cache.data)
|
||||
data.add(cache.data)
|
||||
}
|
||||
|
||||
data class GUIMeshStruct(
|
||||
|
@ -47,7 +47,7 @@ class GUIMeshCache(
|
||||
}
|
||||
|
||||
override fun addCache(cache: GUIMeshCache) {
|
||||
data.addAll(cache.data)
|
||||
data.add(cache.data)
|
||||
revision++
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,9 @@ import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.PrimitiveType
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.AbstractFloatList
|
||||
|
||||
class ParticleMesh(renderWindow: RenderWindow, data: DirectArrayFloatList) : Mesh(renderWindow, ParticleMeshStruct, PrimitiveTypes.POINT, -1, clearOnLoad = false, data = data) {
|
||||
class ParticleMesh(renderWindow: RenderWindow, data: AbstractFloatList) : Mesh(renderWindow, ParticleMeshStruct, PrimitiveTypes.POINT, -1, clearOnLoad = false, data = data) {
|
||||
|
||||
fun addVertex(position: Vec3d, scale: Float, texture: AbstractTexture, tintColor: RGBColor, uvMin: FloatArray? = null, uvMax: FloatArray? = null, light: Int) {
|
||||
val minTransformedUV = if (uvMin == null) {
|
||||
@ -38,8 +38,8 @@ class ParticleMesh(renderWindow: RenderWindow, data: DirectArrayFloatList) : Mes
|
||||
data.add(position.x.toFloat())
|
||||
data.add(position.y.toFloat())
|
||||
data.add(position.z.toFloat())
|
||||
data.addAll(minTransformedUV)
|
||||
data.addAll(maxTransformedUV)
|
||||
data.add(minTransformedUV)
|
||||
data.add(maxTransformedUV)
|
||||
data.add(texture.renderData.shaderTextureId.buffer())
|
||||
data.add(scale)
|
||||
data.add(tintColor.rgba.buffer())
|
||||
|
@ -39,7 +39,7 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnectionStates
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.KUtil.minosoft
|
||||
import de.bixilon.minosoft.util.chunk.ChunkUtil.isInViewDistance
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.BufferedArrayFloatList
|
||||
|
||||
|
||||
class ParticleRenderer(
|
||||
@ -52,8 +52,8 @@ class ParticleRenderer(
|
||||
private val translucentShader = renderSystem.createShader(minosoft("particle")) { ParticleShader(it, false) }
|
||||
|
||||
// There is no opaque mesh because it is simply not needed (every particle has transparency)
|
||||
private var transparentMesh = ParticleMesh(renderWindow, DirectArrayFloatList(RenderConstants.MAXIMUM_PARTICLE_AMOUNT * ParticleMesh.ParticleMeshStruct.FLOATS_PER_VERTEX))
|
||||
private var translucentMesh = ParticleMesh(renderWindow, DirectArrayFloatList(RenderConstants.MAXIMUM_PARTICLE_AMOUNT * ParticleMesh.ParticleMeshStruct.FLOATS_PER_VERTEX))
|
||||
private var transparentMesh = ParticleMesh(renderWindow, BufferedArrayFloatList(RenderConstants.MAXIMUM_PARTICLE_AMOUNT * ParticleMesh.ParticleMeshStruct.FLOATS_PER_VERTEX))
|
||||
private var translucentMesh = ParticleMesh(renderWindow, BufferedArrayFloatList(RenderConstants.MAXIMUM_PARTICLE_AMOUNT * ParticleMesh.ParticleMeshStruct.FLOATS_PER_VERTEX))
|
||||
|
||||
private val particlesLock = SimpleLock()
|
||||
private var particles: MutableList<Particle> = mutableListOf()
|
||||
|
@ -14,7 +14,6 @@
|
||||
package de.bixilon.minosoft.gui.rendering.sky.box
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.MeshUtil.buffer
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.PrimitiveTypes
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.PositionOnlyMeshStruct
|
||||
@ -22,27 +21,28 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.PositionOnlyMeshStruct
|
||||
class SkyboxMesh(renderWindow: RenderWindow) : Mesh(renderWindow, PositionOnlyMeshStruct, PrimitiveTypes.TRIANGLE, initialCacheSize = 6 * 2 * 3 * PositionOnlyMeshStruct.FLOATS_PER_VERTEX) {
|
||||
|
||||
init {
|
||||
data.addAll(floatArrayOf(
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
+1.0f, +1.0f, -1.0f,
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
data.add(
|
||||
floatArrayOf(
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
+1.0f, +1.0f, -1.0f,
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
|
||||
-1.0f, -1.0f, +1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
-1.0f, +1.0f, +1.0f,
|
||||
-1.0f, -1.0f, +1.0f,
|
||||
-1.0f, -1.0f, +1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
-1.0f, +1.0f, -1.0f,
|
||||
-1.0f, +1.0f, +1.0f,
|
||||
-1.0f, -1.0f, +1.0f,
|
||||
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
+1.0f, -1.0f, +1.0f,
|
||||
+1.0f, +1.0f, +1.0f,
|
||||
+1.0f, +1.0f, +1.0f,
|
||||
+1.0f, +1.0f, -1.0f,
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
+1.0f, -1.0f, +1.0f,
|
||||
+1.0f, +1.0f, +1.0f,
|
||||
+1.0f, +1.0f, +1.0f,
|
||||
+1.0f, +1.0f, -1.0f,
|
||||
+1.0f, -1.0f, -1.0f,
|
||||
|
||||
-1.0f, -1.0f, +1.0f,
|
||||
-1.0f, +1.0f, +1.0f,
|
||||
|
@ -23,7 +23,7 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
||||
class SkyboxTextureMesh(renderWindow: RenderWindow) : Mesh(renderWindow, SkyboxTextureMeshStruct, PrimitiveTypes.TRIANGLE, initialCacheSize = 6 * 2 * 3 * SkyboxTextureMeshStruct.FLOATS_PER_VERTEX) {
|
||||
|
||||
init {
|
||||
data.addAll(
|
||||
data.add(
|
||||
floatArrayOf(
|
||||
-1.0f, +1.0f, -1.0f, 0.buffer(),
|
||||
-1.0f, -1.0f, -1.0f, 3.buffer(),
|
||||
|
@ -25,7 +25,7 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
||||
class CloudMesh(renderWindow: RenderWindow) : Mesh(renderWindow, CloudMeshStruct, renderWindow.renderSystem.preferredPrimitiveType) {
|
||||
|
||||
fun addVertex(start: Vec3, side: Directions) {
|
||||
data.addAll(start.array)
|
||||
data.add(start.array)
|
||||
data.add(side.ordinal.buffer())
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.PositionOnlyMeshStruct
|
||||
class SunScatterMesh(renderWindow: RenderWindow) : Mesh(renderWindow, PositionOnlyMeshStruct, PrimitiveTypes.TRIANGLE, initialCacheSize = 6 * 2 * 3 * PositionOnlyMeshStruct.FLOATS_PER_VERTEX) {
|
||||
|
||||
init {
|
||||
data.addAll(
|
||||
data.add(
|
||||
floatArrayOf(
|
||||
-1.0f, +0.2f, -1.0f,
|
||||
-1.0f, -0.2f, -1.0f,
|
||||
|
@ -29,6 +29,8 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager
|
||||
import de.bixilon.minosoft.gui.rendering.system.opengl.OpenGLRenderSystem
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import de.bixilon.minosoft.util.collections.floats.AbstractFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
@ -117,6 +119,13 @@ interface RenderSystem {
|
||||
fun createNativeShader(vertex: ResourceLocation, geometry: ResourceLocation? = null, fragment: ResourceLocation): NativeShader
|
||||
|
||||
fun createVertexBuffer(structure: MeshStruct, data: FloatBuffer, primitiveType: PrimitiveTypes = preferredPrimitiveType): FloatVertexBuffer
|
||||
fun createVertexBuffer(structure: MeshStruct, data: AbstractFloatList, primitiveType: PrimitiveTypes = preferredPrimitiveType): FloatVertexBuffer {
|
||||
if (data is DirectArrayFloatList) {
|
||||
return createVertexBuffer(structure, data.toBuffer(), primitiveType)
|
||||
}
|
||||
return createVertexBuffer(structure, FloatBuffer.wrap(data.toArray()), primitiveType)
|
||||
}
|
||||
|
||||
fun createIntUniformBuffer(data: IntArray = IntArray(0)): IntUniformBuffer
|
||||
fun createFloatUniformBuffer(data: FloatBuffer): FloatUniformBuffer
|
||||
fun createFramebuffer(): Framebuffer
|
||||
|
@ -18,8 +18,9 @@ import de.bixilon.minosoft.gui.rendering.system.base.buffer.RenderableBufferDraw
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.buffer.RenderableBufferStates
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.buffer.RenderableBufferTypes
|
||||
import de.bixilon.minosoft.gui.rendering.system.opengl.OpenGLRenderSystem
|
||||
import org.lwjgl.opengl.GL15.glBufferData
|
||||
import org.lwjgl.opengl.GL15.glBufferSubData
|
||||
import org.lwjgl.opengl.GL15C
|
||||
import org.lwjgl.system.MemoryUtil.memAddress
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
open class FloatOpenGLBuffer(renderSystem: OpenGLRenderSystem, protected var _data: FloatBuffer?) : OpenGLRenderableBuffer(renderSystem, RenderableBufferTypes.ARRAY_BUFFER), RenderFloatBuffer {
|
||||
@ -33,7 +34,7 @@ open class FloatOpenGLBuffer(renderSystem: OpenGLRenderSystem, protected var _da
|
||||
override fun initialUpload() {
|
||||
bind()
|
||||
buffer.flip()
|
||||
glBufferData(type.gl, buffer, drawTypes.gl)
|
||||
nglBufferData(type.gl, buffer, drawTypes.gl)
|
||||
unbind()
|
||||
state = RenderableBufferStates.UPLOADED
|
||||
}
|
||||
@ -43,4 +44,8 @@ open class FloatOpenGLBuffer(renderSystem: OpenGLRenderSystem, protected var _da
|
||||
glBufferSubData(type.gl, 0, buffer)
|
||||
unbind()
|
||||
}
|
||||
|
||||
private fun nglBufferData(target: Int, buffer: FloatBuffer, usage: Int) {
|
||||
GL15C.nglBufferData(target, Integer.toUnsignedLong(buffer.remaining()) shl 2, memAddress(buffer), usage)
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,13 @@ package de.bixilon.minosoft.gui.rendering.util.mesh
|
||||
|
||||
import de.bixilon.kotlinglm.vec2.Vec2
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kutil.cast.CastUtil.unsafeCast
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.FloatVertexBuffer
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.PrimitiveTypes
|
||||
import de.bixilon.minosoft.util.collections.floats.AbstractFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
import de.bixilon.minosoft.util.collections.floats.FloatListUtil
|
||||
|
||||
abstract class Mesh(
|
||||
val renderWindow: RenderWindow,
|
||||
@ -26,18 +29,18 @@ abstract class Mesh(
|
||||
private val primitiveType: PrimitiveTypes = renderWindow.renderSystem.preferredPrimitiveType,
|
||||
var initialCacheSize: Int = 10000,
|
||||
val clearOnLoad: Boolean = true,
|
||||
data: DirectArrayFloatList? = null,
|
||||
data: AbstractFloatList? = null,
|
||||
val onDemand: Boolean = false,
|
||||
) : AbstractVertexConsumer {
|
||||
override val order = renderWindow.renderSystem.primitiveMeshOrder
|
||||
val reversedOrder = order.reversedArray()
|
||||
private var _data: DirectArrayFloatList? = data ?: if (onDemand) null else DirectArrayFloatList(initialCacheSize)
|
||||
var data: DirectArrayFloatList
|
||||
private var _data: AbstractFloatList? = data ?: if (onDemand) null else FloatListUtil.direct(initialCacheSize)
|
||||
var data: AbstractFloatList
|
||||
get() {
|
||||
if (_data == null && onDemand) {
|
||||
_data = DirectArrayFloatList(initialCacheSize)
|
||||
_data = FloatListUtil.direct(initialCacheSize)
|
||||
}
|
||||
return _data as DirectArrayFloatList
|
||||
return _data.unsafeCast()
|
||||
}
|
||||
set(value) {
|
||||
_data = value
|
||||
@ -53,10 +56,13 @@ abstract class Mesh(
|
||||
|
||||
|
||||
fun load() {
|
||||
buffer = renderWindow.renderSystem.createVertexBuffer(struct, data.buffer, primitiveType)
|
||||
val data = this.data
|
||||
buffer = renderWindow.renderSystem.createVertexBuffer(struct, data, primitiveType)
|
||||
buffer.init()
|
||||
if (clearOnLoad) {
|
||||
data.unload()
|
||||
if (data is DirectArrayFloatList) {
|
||||
data.unload()
|
||||
}
|
||||
_data = null
|
||||
}
|
||||
vertices = buffer.vertices
|
||||
|
@ -23,27 +23,28 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
||||
class WorldBorderMesh(renderWindow: RenderWindow) : Mesh(renderWindow, WorldBorderMeshStruct, PrimitiveTypes.TRIANGLE, initialCacheSize = 6 * 2 * 3 * WorldBorderMeshStruct.FLOATS_PER_VERTEX) {
|
||||
|
||||
init {
|
||||
data.addAll(floatArrayOf(
|
||||
-1.0f, +1.0f, -1.0f, 1.buffer(),
|
||||
+1.0f, -1.0f, -1.0f, 0.buffer(),
|
||||
-1.0f, -1.0f, -1.0f, 3.buffer(),
|
||||
+1.0f, -1.0f, -1.0f, 0.buffer(),
|
||||
-1.0f, +1.0f, -1.0f, 1.buffer(),
|
||||
+1.0f, +1.0f, -1.0f, 2.buffer(),
|
||||
data.add(
|
||||
floatArrayOf(
|
||||
-1.0f, +1.0f, -1.0f, 1.buffer(),
|
||||
+1.0f, -1.0f, -1.0f, 0.buffer(),
|
||||
-1.0f, -1.0f, -1.0f, 3.buffer(),
|
||||
+1.0f, -1.0f, -1.0f, 0.buffer(),
|
||||
-1.0f, +1.0f, -1.0f, 1.buffer(),
|
||||
+1.0f, +1.0f, -1.0f, 2.buffer(),
|
||||
|
||||
-1.0f, -1.0f, +1.0f, 3.buffer(),
|
||||
-1.0f, +1.0f, -1.0f, 2.buffer(),
|
||||
-1.0f, -1.0f, -1.0f, 0.buffer(),
|
||||
-1.0f, +1.0f, -1.0f, 2.buffer(),
|
||||
-1.0f, -1.0f, +1.0f, 3.buffer(),
|
||||
-1.0f, +1.0f, +1.0f, 1.buffer(),
|
||||
-1.0f, -1.0f, +1.0f, 3.buffer(),
|
||||
-1.0f, +1.0f, -1.0f, 2.buffer(),
|
||||
-1.0f, -1.0f, -1.0f, 0.buffer(),
|
||||
-1.0f, +1.0f, -1.0f, 2.buffer(),
|
||||
-1.0f, -1.0f, +1.0f, 3.buffer(),
|
||||
-1.0f, +1.0f, +1.0f, 1.buffer(),
|
||||
|
||||
+1.0f, -1.0f, -1.0f, 3.buffer(),
|
||||
+1.0f, +1.0f, +1.0f, 2.buffer(),
|
||||
+1.0f, -1.0f, +1.0f, 0.buffer(),
|
||||
+1.0f, +1.0f, +1.0f, 2.buffer(),
|
||||
+1.0f, -1.0f, -1.0f, 3.buffer(),
|
||||
+1.0f, +1.0f, -1.0f, 1.buffer(),
|
||||
+1.0f, -1.0f, -1.0f, 3.buffer(),
|
||||
+1.0f, +1.0f, +1.0f, 2.buffer(),
|
||||
+1.0f, -1.0f, +1.0f, 0.buffer(),
|
||||
+1.0f, +1.0f, +1.0f, 2.buffer(),
|
||||
+1.0f, -1.0f, -1.0f, 3.buffer(),
|
||||
+1.0f, +1.0f, -1.0f, 1.buffer(),
|
||||
|
||||
-1.0f, -1.0f, +1.0f, 0.buffer(),
|
||||
+1.0f, +1.0f, +1.0f, 1.buffer(),
|
||||
|
@ -30,7 +30,7 @@ class SingleWorldMesh(renderWindow: RenderWindow, initialCacheSize: Int, onDeman
|
||||
data.add(position[0])
|
||||
data.add(position[1])
|
||||
data.add(position[2])
|
||||
data.addAll(transformedUV)
|
||||
data.add(transformedUV)
|
||||
data.add(texture.renderData.shaderTextureId.buffer())
|
||||
data.add((tintColor or (light shl 24)).buffer())
|
||||
}
|
||||
@ -41,7 +41,7 @@ class SingleWorldMesh(renderWindow: RenderWindow, initialCacheSize: Int, onDeman
|
||||
data.add(x)
|
||||
data.add(y)
|
||||
data.add(z)
|
||||
data.addAll(transformedUV)
|
||||
data.add(transformedUV)
|
||||
data.add(shaderTextureId)
|
||||
data.add(tintLight)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import de.bixilon.kotlinglm.vec3.Vec3i
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
||||
import de.bixilon.minosoft.gui.rendering.world.entities.BlockEntityRenderer
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
|
||||
class WorldMesh(
|
||||
renderWindow: RenderWindow,
|
||||
@ -30,7 +31,7 @@ class WorldMesh(
|
||||
var opaqueMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 100000)
|
||||
var translucentMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 10000)
|
||||
var transparentMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 20000)
|
||||
var textMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 200000, onDemand = true)
|
||||
var textMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 50000, onDemand = true)
|
||||
var blockEntities: Set<BlockEntityRenderer<*>>? = null
|
||||
|
||||
// used for frustum culling
|
||||
@ -59,8 +60,11 @@ class WorldMesh(
|
||||
if (mesh == null) {
|
||||
return false
|
||||
}
|
||||
if (mesh.data.isEmpty) {
|
||||
mesh.data.unload()
|
||||
val data = mesh.data
|
||||
if (data.isEmpty) {
|
||||
if (data is DirectArrayFloatList) {
|
||||
data.unload()
|
||||
}
|
||||
return true
|
||||
}
|
||||
meshes++
|
||||
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections
|
||||
|
||||
interface DirectList
|
@ -14,11 +14,16 @@
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import de.bixilon.minosoft.util.collections.AbstractPrimitiveList
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
abstract class AbstractFloatList : AbstractPrimitiveList<Float>() {
|
||||
|
||||
abstract fun addAll(floats: FloatArray)
|
||||
abstract fun addAll(floatList: AbstractFloatList)
|
||||
abstract fun add(array: FloatArray)
|
||||
operator fun plusAssign(array: FloatArray) = add(array)
|
||||
abstract fun add(floatList: AbstractFloatList)
|
||||
operator fun plusAssign(floatList: AbstractFloatList) = add(floatList)
|
||||
abstract fun add(buffer: FloatBuffer)
|
||||
operator fun plusAssign(buffer: FloatBuffer) = add(buffer)
|
||||
|
||||
abstract fun toArray(): FloatArray
|
||||
}
|
||||
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import de.bixilon.minosoft.util.collections.floats.FloatListUtil.copy
|
||||
import de.bixilon.minosoft.util.collections.floats.FloatListUtil.finish
|
||||
import org.lwjgl.system.MemoryUtil.memAllocFloat
|
||||
import org.lwjgl.system.MemoryUtil.memFree
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
class BufferedArrayFloatList(
|
||||
initialSize: Int = FloatListUtil.DEFAULT_INITIAL_SIZE,
|
||||
) : AbstractFloatList(), DirectArrayFloatList {
|
||||
var buffer: FloatBuffer = memAllocFloat(initialSize)
|
||||
private set
|
||||
override var limit: Int = buffer.limit()
|
||||
private set
|
||||
override val size: Int
|
||||
get() = buffer.position()
|
||||
override val isEmpty: Boolean
|
||||
get() = size == 0
|
||||
private var unloaded = false
|
||||
|
||||
private val nextGrowStep = when {
|
||||
initialSize <= 0 -> FloatListUtil.DEFAULT_INITIAL_SIZE
|
||||
initialSize <= 100 -> 100
|
||||
else -> initialSize
|
||||
}
|
||||
|
||||
private var output: FloatArray = FloatArray(0)
|
||||
private var outputUpToDate = false
|
||||
|
||||
override fun ensureSize(needed: Int) {
|
||||
checkFinished()
|
||||
if (limit - size >= needed) {
|
||||
return
|
||||
}
|
||||
var newSize = limit
|
||||
newSize += if (nextGrowStep < needed) {
|
||||
(needed / nextGrowStep + 1) * nextGrowStep
|
||||
} else {
|
||||
nextGrowStep
|
||||
}
|
||||
grow(newSize)
|
||||
}
|
||||
|
||||
private fun grow(size: Int) {
|
||||
val buffer = buffer
|
||||
this.buffer = memAllocFloat(size)
|
||||
limit = size
|
||||
buffer.copy(this.buffer)
|
||||
memFree(buffer)
|
||||
}
|
||||
|
||||
override fun add(value: Float) {
|
||||
ensureSize(1)
|
||||
buffer.put(value)
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun add(array: FloatArray) {
|
||||
ensureSize(array.size)
|
||||
buffer.put(array)
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun add(buffer: FloatBuffer) {
|
||||
ensureSize(buffer.position())
|
||||
buffer.copy(this.buffer)
|
||||
}
|
||||
|
||||
override fun add(floatList: AbstractFloatList) {
|
||||
ensureSize(floatList.size)
|
||||
when (floatList) {
|
||||
is FragmentedArrayFloatList -> {
|
||||
for (buffer in floatList.fragments) {
|
||||
buffer.copy(this.buffer)
|
||||
}
|
||||
}
|
||||
|
||||
is DirectArrayFloatList -> floatList.toBuffer().copy(this.buffer)
|
||||
else -> add(floatList.toArray())
|
||||
}
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
private fun checkOutputArray() {
|
||||
if (outputUpToDate) {
|
||||
return
|
||||
}
|
||||
val position = buffer.position()
|
||||
output = FloatArray(position)
|
||||
buffer.position(0)
|
||||
buffer.get(output, 0, position)
|
||||
buffer.position(position)
|
||||
outputUpToDate = true
|
||||
}
|
||||
|
||||
override fun toArray(): FloatArray {
|
||||
checkOutputArray()
|
||||
return output
|
||||
}
|
||||
|
||||
override fun unload() {
|
||||
check(!unloaded) { "Already unloaded!" }
|
||||
unloaded = true
|
||||
finished = true // Is unloaded
|
||||
memFree(buffer)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
buffer.clear()
|
||||
if (output.isNotEmpty()) {
|
||||
output = FloatArray(0)
|
||||
}
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
finished = true
|
||||
limit = buffer.limit()
|
||||
this.buffer = buffer.finish()
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
if (unloaded) {
|
||||
return
|
||||
}
|
||||
memFree(buffer)
|
||||
}
|
||||
|
||||
override fun toBuffer(): FloatBuffer {
|
||||
return this.buffer
|
||||
}
|
||||
|
||||
private fun invalidateOutput() {
|
||||
if (outputUpToDate) {
|
||||
outputUpToDate = false
|
||||
}
|
||||
}
|
||||
}
|
@ -13,159 +13,11 @@
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import de.bixilon.kutil.exception.ExceptionUtil.catchAll
|
||||
import org.lwjgl.system.MemoryUtil.memAllocFloat
|
||||
import org.lwjgl.system.MemoryUtil.memFree
|
||||
import java.nio.BufferOverflowException
|
||||
import de.bixilon.minosoft.util.collections.DirectList
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
class DirectArrayFloatList(
|
||||
initialSize: Int = DEFAULT_INITIAL_SIZE,
|
||||
) : AbstractFloatList() {
|
||||
var buffer: FloatBuffer = memAllocFloat(initialSize)
|
||||
private set
|
||||
override var limit: Int = buffer.limit()
|
||||
private set
|
||||
override val size: Int
|
||||
get() = buffer.position()
|
||||
override val isEmpty: Boolean
|
||||
get() = size == 0
|
||||
private var unloaded = false
|
||||
interface DirectArrayFloatList : DirectList {
|
||||
|
||||
private val nextGrowStep = when {
|
||||
initialSize <= 0 -> DEFAULT_INITIAL_SIZE
|
||||
initialSize <= 100 -> 100
|
||||
else -> initialSize
|
||||
}
|
||||
|
||||
private var output: FloatArray = FloatArray(0)
|
||||
private var outputUpToDate = false
|
||||
|
||||
override fun ensureSize(needed: Int) {
|
||||
checkFinished()
|
||||
if (limit - size >= needed) {
|
||||
return
|
||||
}
|
||||
var newSize = limit
|
||||
newSize += if (nextGrowStep < needed) {
|
||||
(needed / nextGrowStep + 1) * nextGrowStep
|
||||
} else {
|
||||
nextGrowStep
|
||||
}
|
||||
grow(newSize)
|
||||
}
|
||||
|
||||
private fun grow(size: Int) {
|
||||
val oldBuffer = buffer
|
||||
buffer = memAllocFloat(size)
|
||||
limit = size
|
||||
if (FLOAT_PUT_METHOD == null) { // Java < 16
|
||||
for (i in 0 until oldBuffer.position()) {
|
||||
buffer.put(oldBuffer.get(i))
|
||||
}
|
||||
} else {
|
||||
FLOAT_PUT_METHOD.invoke(buffer, 0, oldBuffer, 0, oldBuffer.position())
|
||||
buffer.position(oldBuffer.position())
|
||||
}
|
||||
memFree(oldBuffer)
|
||||
}
|
||||
|
||||
override fun add(value: Float) {
|
||||
ensureSize(1)
|
||||
buffer.put(value)
|
||||
if (outputUpToDate) {
|
||||
outputUpToDate = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun addAll(floats: FloatArray) {
|
||||
ensureSize(floats.size)
|
||||
try {
|
||||
buffer.put(floats)
|
||||
} catch (exception: BufferOverflowException) {
|
||||
ensureSize(floats.size)
|
||||
|
||||
exception.printStackTrace()
|
||||
}
|
||||
if (outputUpToDate) {
|
||||
outputUpToDate = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun addAll(floatList: AbstractFloatList) {
|
||||
if (floatList is DirectArrayFloatList) {
|
||||
ensureSize(floatList.size)
|
||||
if (FLOAT_PUT_METHOD == null) { // Java < 16
|
||||
for (i in 0 until floatList.buffer.position()) {
|
||||
buffer.put(floatList.buffer.get(i))
|
||||
}
|
||||
} else {
|
||||
FLOAT_PUT_METHOD.invoke(buffer, buffer.position(), floatList.buffer, 0, floatList.buffer.position())
|
||||
buffer.position(buffer.position() + floatList.buffer.position())
|
||||
}
|
||||
} else {
|
||||
addAll(floatList.toArray())
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkOutputArray() {
|
||||
if (outputUpToDate) {
|
||||
return
|
||||
}
|
||||
val position = buffer.position()
|
||||
output = FloatArray(position)
|
||||
buffer.position(0)
|
||||
buffer.get(output, 0, position)
|
||||
buffer.position(position)
|
||||
outputUpToDate = true
|
||||
}
|
||||
|
||||
override fun toArray(): FloatArray {
|
||||
checkOutputArray()
|
||||
return output
|
||||
}
|
||||
|
||||
fun unload() {
|
||||
check(!unloaded) { "Already unloaded!" }
|
||||
unloaded = true
|
||||
finished = true // Is unloaded
|
||||
memFree(buffer)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
buffer.clear()
|
||||
if (output.isNotEmpty()) {
|
||||
output = FloatArray(0)
|
||||
}
|
||||
outputUpToDate = false
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
finished = true
|
||||
val oldBuffer = buffer
|
||||
buffer = memAllocFloat(oldBuffer.position())
|
||||
limit = buffer.limit()
|
||||
if (FLOAT_PUT_METHOD == null) { // Java < 16
|
||||
for (i in 0 until oldBuffer.position()) {
|
||||
buffer.put(oldBuffer.get(i))
|
||||
}
|
||||
} else {
|
||||
FLOAT_PUT_METHOD.invoke(buffer, 0, oldBuffer, 0, oldBuffer.position())
|
||||
buffer.position(buffer.limit())
|
||||
}
|
||||
memFree(oldBuffer)
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
if (unloaded) {
|
||||
return
|
||||
}
|
||||
memFree(buffer)
|
||||
}
|
||||
|
||||
|
||||
private companion object {
|
||||
private val FLOAT_PUT_METHOD = catchAll { FloatBuffer::class.java.getMethod("put", Int::class.java, FloatBuffer::class.java, Int::class.java, Int::class.java) }
|
||||
private const val DEFAULT_INITIAL_SIZE = 1000
|
||||
}
|
||||
fun toBuffer(): FloatBuffer
|
||||
fun unload()
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import de.bixilon.kutil.exception.ExceptionUtil
|
||||
import org.lwjgl.system.MemoryUtil
|
||||
import org.lwjgl.system.MemoryUtil.memAllocFloat
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
object FloatListUtil {
|
||||
const val PREFER_FRAGMENTED = true
|
||||
|
||||
val FLOAT_PUT_METHOD = ExceptionUtil.catchAll { FloatBuffer::class.java.getMethod("put", Int::class.java, FloatBuffer::class.java, Int::class.java, Int::class.java) }
|
||||
const val DEFAULT_INITIAL_SIZE = 1000
|
||||
|
||||
fun direct(initialSize: Int = DEFAULT_INITIAL_SIZE): AbstractFloatList {
|
||||
return if (PREFER_FRAGMENTED) FragmentedArrayFloatList(initialSize) else BufferedArrayFloatList(initialSize)
|
||||
}
|
||||
|
||||
fun FloatBuffer.finish(): FloatBuffer {
|
||||
val buffer = memAllocFloat(position())
|
||||
if (FLOAT_PUT_METHOD == null) { // Java < 16
|
||||
for (i in 0 until position()) {
|
||||
buffer.put(get(i))
|
||||
}
|
||||
} else {
|
||||
FLOAT_PUT_METHOD.invoke(buffer, 0, this, 0, position())
|
||||
buffer.position(buffer.limit())
|
||||
}
|
||||
MemoryUtil.memFree(this)
|
||||
return buffer
|
||||
}
|
||||
|
||||
fun FloatBuffer.copy(sourceOffset: Int, destination: FloatBuffer, destinationOffset: Int, length: Int) {
|
||||
if (length == 0) {
|
||||
return
|
||||
}
|
||||
if (FLOAT_PUT_METHOD == null) { // Java < 16
|
||||
for (i in 0 until length) {
|
||||
destination.put(destinationOffset + i, this.get(sourceOffset + i))
|
||||
}
|
||||
return
|
||||
}
|
||||
FLOAT_PUT_METHOD.invoke(destination, destinationOffset, this, sourceOffset, length)
|
||||
destination.position(destination.position() + length)
|
||||
}
|
||||
|
||||
fun FloatBuffer.copy(destination: FloatBuffer) {
|
||||
copy(0, destination, destination.position(), position())
|
||||
}
|
||||
}
|
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import de.bixilon.minosoft.util.collections.floats.FloatListUtil.copy
|
||||
import org.lwjgl.system.MemoryUtil.memAllocFloat
|
||||
import org.lwjgl.system.MemoryUtil.memFree
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
class FragmentedArrayFloatList(
|
||||
initialSize: Int = FloatListUtil.DEFAULT_INITIAL_SIZE,
|
||||
) : AbstractFloatList(), DirectArrayFloatList {
|
||||
var fragments: MutableList<FloatBuffer> = mutableListOf()
|
||||
override var limit: Int = 0
|
||||
private set
|
||||
override var size: Int = 0
|
||||
private set
|
||||
override val isEmpty: Boolean
|
||||
get() = size == 0
|
||||
private var unloaded = false
|
||||
|
||||
private val nextGrowStep = when {
|
||||
initialSize <= 0 -> FloatListUtil.DEFAULT_INITIAL_SIZE
|
||||
initialSize <= 100 -> 100
|
||||
else -> initialSize
|
||||
}
|
||||
|
||||
private var output: FloatArray? = null
|
||||
private var buffer: FloatBuffer? = null
|
||||
|
||||
|
||||
override fun ensureSize(needed: Int) {
|
||||
grow(needed)
|
||||
}
|
||||
|
||||
private fun grow(size: Int): FloatBuffer {
|
||||
checkFinished()
|
||||
if (limit - this.size >= size) {
|
||||
return this.fragments.last()
|
||||
}
|
||||
val grow = if (nextGrowStep < size) {
|
||||
(size / nextGrowStep + 1) * nextGrowStep
|
||||
} else {
|
||||
nextGrowStep
|
||||
}
|
||||
return forceGrow(grow)
|
||||
}
|
||||
|
||||
private fun forceGrow(size: Int): FloatBuffer {
|
||||
val last = fragments.lastOrNull()
|
||||
val buffer = memAllocFloat(size)
|
||||
fragments += buffer
|
||||
limit += size
|
||||
return buffer
|
||||
}
|
||||
|
||||
override fun add(value: Float) {
|
||||
val buffer = grow(1)
|
||||
if (buffer.position() >= buffer.limit()) {
|
||||
println()
|
||||
}
|
||||
buffer.put(value)
|
||||
size += 1
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun add(array: FloatArray) {
|
||||
if (array.isEmpty()) return
|
||||
invalidateOutput()
|
||||
|
||||
var offset = 0
|
||||
size += array.size
|
||||
if (fragments.isNotEmpty()) {
|
||||
val fragment = fragments.last()
|
||||
val remaining = fragment.limit() - fragment.position()
|
||||
val copy = minOf(array.size, remaining)
|
||||
fragment.put(array, 0, copy)
|
||||
offset += copy
|
||||
|
||||
if (array.size <= remaining) {
|
||||
// everything copied
|
||||
return
|
||||
}
|
||||
}
|
||||
val length = array.size - offset
|
||||
val next = grow(length)
|
||||
next.put(array, offset, length)
|
||||
next.position(length)
|
||||
}
|
||||
|
||||
override fun add(buffer: FloatBuffer) {
|
||||
if (buffer.position() == 0) return
|
||||
invalidateOutput()
|
||||
|
||||
var offset = 0
|
||||
val position = buffer.position()
|
||||
size += position
|
||||
if (fragments.isNotEmpty()) {
|
||||
val fragment = fragments.last()
|
||||
val remaining = fragment.limit() - fragment.position()
|
||||
val copy = minOf(position, remaining)
|
||||
buffer.copy(0, fragment, fragment.position(), copy)
|
||||
offset += copy
|
||||
|
||||
if (position <= remaining) {
|
||||
// everything copied
|
||||
return
|
||||
}
|
||||
}
|
||||
val length = position - offset
|
||||
val next = grow(length)
|
||||
buffer.copy(offset, next, 0, length)
|
||||
next.position(length)
|
||||
}
|
||||
|
||||
override fun add(floatList: AbstractFloatList) {
|
||||
when (floatList) {
|
||||
is FragmentedArrayFloatList -> {
|
||||
// TODO: add dirty method (just adding their fragments to our list of fragments)
|
||||
for (buffer in floatList.fragments) {
|
||||
add(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
is DirectArrayFloatList -> add(floatList.toBuffer())
|
||||
else -> add(floatList.toArray())
|
||||
}
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
private fun checkOutputArray(): FloatArray {
|
||||
this.output?.let { return it }
|
||||
val output = FloatArray(size)
|
||||
var offset = 0
|
||||
for (buffer in fragments) {
|
||||
val position = buffer.position()
|
||||
buffer.position(0)
|
||||
buffer.get(output, offset, position)
|
||||
offset += position
|
||||
buffer.position(position)
|
||||
}
|
||||
this.output = output
|
||||
return output
|
||||
}
|
||||
|
||||
override fun toArray(): FloatArray {
|
||||
return checkOutputArray()
|
||||
}
|
||||
|
||||
override fun unload() {
|
||||
check(!unloaded) { "Already unloaded!" }
|
||||
unloaded = true
|
||||
finished = true // Is unloaded
|
||||
for (buffer in fragments) {
|
||||
memFree(buffer)
|
||||
}
|
||||
this.output = null
|
||||
val buffer = this.buffer
|
||||
if (buffer != null) {
|
||||
memFree(buffer)
|
||||
this.buffer = null
|
||||
}
|
||||
fragments.clear()
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
size = 0
|
||||
for (buffer in fragments) {
|
||||
buffer.clear()
|
||||
}
|
||||
if (output != null) {
|
||||
output = null
|
||||
}
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
finished = true
|
||||
if (fragments.isEmpty()) {
|
||||
return
|
||||
}
|
||||
val last = fragments.removeLast()
|
||||
val next = memAllocFloat(last.position())
|
||||
last.copy(next)
|
||||
fragments += next
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
if (unloaded) {
|
||||
return
|
||||
}
|
||||
for (buffer in fragments) {
|
||||
memFree(buffer)
|
||||
}
|
||||
fragments.clear()
|
||||
}
|
||||
|
||||
private fun invalidateOutput() {
|
||||
if (this.output != null) {
|
||||
this.output = null
|
||||
}
|
||||
|
||||
if (this.buffer != null) {
|
||||
this.buffer = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun toBuffer(): FloatBuffer {
|
||||
this.buffer?.let { return it }
|
||||
if (fragments.size == 1) {
|
||||
return fragments.first()
|
||||
}
|
||||
val buffer = memAllocFloat(size)
|
||||
for (fragment in fragments) {
|
||||
fragment.copy(buffer)
|
||||
}
|
||||
this.buffer = buffer
|
||||
return buffer
|
||||
}
|
||||
}
|
@ -12,8 +12,10 @@
|
||||
*/
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
class HeapArrayFloatList(
|
||||
initialSize: Int = DEFAULT_INITIAL_SIZE,
|
||||
initialSize: Int = FloatListUtil.DEFAULT_INITIAL_SIZE,
|
||||
) : AbstractFloatList() {
|
||||
private var data: FloatArray = FloatArray(initialSize)
|
||||
override val limit: Int
|
||||
@ -23,7 +25,7 @@ class HeapArrayFloatList(
|
||||
get() = size == 0
|
||||
|
||||
private val nextGrowStep = when {
|
||||
initialSize <= 0 -> DEFAULT_INITIAL_SIZE
|
||||
initialSize <= 0 -> FloatListUtil.DEFAULT_INITIAL_SIZE
|
||||
initialSize <= 50 -> 50
|
||||
else -> initialSize
|
||||
}
|
||||
@ -40,7 +42,7 @@ class HeapArrayFloatList(
|
||||
override fun clear() {
|
||||
checkFinalized()
|
||||
size = 0
|
||||
outputUpToDate = false
|
||||
invalidateOutput()
|
||||
output = FloatArray(0)
|
||||
}
|
||||
|
||||
@ -65,21 +67,27 @@ class HeapArrayFloatList(
|
||||
override fun add(value: Float) {
|
||||
ensureSize(1)
|
||||
data[size++] = value
|
||||
if (outputUpToDate) {
|
||||
outputUpToDate = false
|
||||
}
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun addAll(floats: FloatArray) {
|
||||
ensureSize(floats.size)
|
||||
System.arraycopy(floats, 0, data, size, floats.size)
|
||||
size += floats.size
|
||||
if (outputUpToDate) {
|
||||
outputUpToDate = false
|
||||
}
|
||||
override fun add(array: FloatArray) {
|
||||
ensureSize(array.size)
|
||||
System.arraycopy(array, 0, data, size, array.size)
|
||||
size += array.size
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun addAll(floatList: AbstractFloatList) {
|
||||
override fun add(buffer: FloatBuffer) {
|
||||
val position = buffer.position()
|
||||
ensureSize(position)
|
||||
for (i in 0 until position) {
|
||||
data[size + i] = buffer.get(i)
|
||||
}
|
||||
size += position
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
override fun add(floatList: AbstractFloatList) {
|
||||
ensureSize(floatList.size)
|
||||
val source: FloatArray = if (floatList is HeapArrayFloatList) {
|
||||
if (floatList.finished) {
|
||||
@ -92,9 +100,7 @@ class HeapArrayFloatList(
|
||||
}
|
||||
System.arraycopy(source, 0, data, size, floatList.size)
|
||||
size += floatList.size
|
||||
if (outputUpToDate) {
|
||||
outputUpToDate = false
|
||||
}
|
||||
invalidateOutput()
|
||||
}
|
||||
|
||||
private fun checkOutputArray() {
|
||||
@ -117,8 +123,9 @@ class HeapArrayFloatList(
|
||||
data = FloatArray(0)
|
||||
}
|
||||
|
||||
|
||||
private companion object {
|
||||
private const val DEFAULT_INITIAL_SIZE = 1000
|
||||
private fun invalidateOutput() {
|
||||
if (outputUpToDate) {
|
||||
outputUpToDate = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.nio.FloatBuffer
|
||||
import kotlin.test.assertContentEquals
|
||||
|
||||
abstract class AbstractFloatListTest {
|
||||
|
||||
abstract fun create(initialSize: Int = 1): AbstractFloatList
|
||||
|
||||
@Test
|
||||
fun initialListSize() {
|
||||
val list = create()
|
||||
assertEquals(0, list.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addSingleFloat() {
|
||||
val list = create()
|
||||
list.add(189.0f)
|
||||
assertEquals(1, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleFloats() {
|
||||
val list = create()
|
||||
list.add(189.0f)
|
||||
list.add(289.0f)
|
||||
list.add(389.0f)
|
||||
assertEquals(3, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addVastFloats() {
|
||||
val list = create()
|
||||
for (i in 0 until 1000) {
|
||||
list.add(i.toFloat() * 2.0f)
|
||||
}
|
||||
assertEquals(1000, list.size)
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1000) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addSingleArray() {
|
||||
val list = create()
|
||||
list.add(floatArrayOf(189.0f))
|
||||
assertEquals(1, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleArrays() {
|
||||
val list = create()
|
||||
list.add(floatArrayOf(189.0f))
|
||||
list.add(floatArrayOf(289.0f))
|
||||
list.add(floatArrayOf(389.0f))
|
||||
assertEquals(3, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleBigArrays() {
|
||||
val list = create()
|
||||
list.add(floatArrayOf(189.0f))
|
||||
list.add(floatArrayOf(289.0f, 389.0f))
|
||||
list.add(floatArrayOf(489.0f, 589.0f, 689.0f))
|
||||
assertEquals(6, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f, 489.0f, 589.0f, 689.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addVastArrays() {
|
||||
val list = create()
|
||||
|
||||
for (i in 0 until 1000) {
|
||||
list.add(floatArrayOf(i.toFloat() * 2.0f))
|
||||
}
|
||||
assertEquals(1000, list.size)
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1000) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addSingleBuffer() {
|
||||
val list = create()
|
||||
list.add(wrap(189.0f))
|
||||
assertEquals(1, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleBuffers() {
|
||||
val list = create()
|
||||
list.add(wrap(189.0f))
|
||||
list.add(wrap(289.0f))
|
||||
list.add(wrap(389.0f))
|
||||
assertEquals(3, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleBigBuffers() {
|
||||
val list = create()
|
||||
list.add(wrap(189.0f))
|
||||
list.add(wrap(289.0f, 389.0f))
|
||||
list.add(wrap(489.0f, 589.0f, 689.0f))
|
||||
assertEquals(6, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f, 489.0f, 589.0f, 689.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addVastBuffers() {
|
||||
val list = create()
|
||||
|
||||
for (i in 0 until 1000) {
|
||||
list.add(wrap(i.toFloat() * 2.0f))
|
||||
}
|
||||
assertEquals(1000, list.size)
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1000) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun addSingleHeapList() {
|
||||
val list = create()
|
||||
list.add(HeapArrayFloatList(1).apply { add(189.0f) })
|
||||
assertEquals(1, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleHeapLists() {
|
||||
val list = create()
|
||||
list.add(HeapArrayFloatList(1).apply { add(189.0f) })
|
||||
list.add(HeapArrayFloatList(1).apply { add(289.0f) })
|
||||
list.add(HeapArrayFloatList(1).apply { add(389.0f) })
|
||||
assertEquals(3, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleBigHeapLists() {
|
||||
val list = create()
|
||||
list.add(HeapArrayFloatList(1).apply { add(189.0f) })
|
||||
list.add(HeapArrayFloatList(1).apply { add(289.0f); add(389.0f) })
|
||||
list.add(HeapArrayFloatList(1).apply { add(489.0f); add(589.0f); add(689.0f) })
|
||||
|
||||
assertEquals(6, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f, 489.0f, 589.0f, 689.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addVastHeapLists() {
|
||||
val list = create()
|
||||
|
||||
for (i in 0 until 1000) {
|
||||
list.add(HeapArrayFloatList(1).apply { add(i.toFloat() * 2.0f) })
|
||||
}
|
||||
assertEquals(1000, list.size)
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1000) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun addSingleBufferedList() {
|
||||
val list = create()
|
||||
list.add(BufferedArrayFloatList(1).apply { add(189.0f) })
|
||||
assertEquals(1, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleBufferedLists() {
|
||||
val list = create()
|
||||
list.add(BufferedArrayFloatList(1).apply { add(189.0f) })
|
||||
list.add(BufferedArrayFloatList(1).apply { add(289.0f) })
|
||||
list.add(BufferedArrayFloatList(1).apply { add(389.0f) })
|
||||
assertEquals(3, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleBigBufferedLists() {
|
||||
val list = create()
|
||||
list.add(BufferedArrayFloatList(1).apply { add(189.0f) })
|
||||
list.add(BufferedArrayFloatList(1).apply { add(289.0f); add(389.0f) })
|
||||
list.add(BufferedArrayFloatList(1).apply { add(489.0f); add(589.0f); add(689.0f) })
|
||||
|
||||
assertEquals(6, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f, 489.0f, 589.0f, 689.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addVastBufferedLists() {
|
||||
val list = create()
|
||||
|
||||
for (i in 0 until 1000) {
|
||||
list.add(BufferedArrayFloatList(1).apply { add(i.toFloat() * 2.0f) })
|
||||
}
|
||||
assertEquals(1000, list.size)
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1000) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addSingleFragmentedList() {
|
||||
val list = create()
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(189.0f) })
|
||||
assertEquals(1, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleFragmentedLists() {
|
||||
val list = create()
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(189.0f) })
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(289.0f) })
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(389.0f) })
|
||||
assertEquals(3, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addMultipleBigFragmentedLists() {
|
||||
val list = create()
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(189.0f) })
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(289.0f); add(389.0f) })
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(489.0f); add(589.0f); add(689.0f) })
|
||||
|
||||
assertEquals(6, list.size)
|
||||
val array = list.toArray()
|
||||
assertContentEquals(floatArrayOf(189.0f, 289.0f, 389.0f, 489.0f, 589.0f, 689.0f), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addVastFragmentedLists() {
|
||||
val list = create()
|
||||
|
||||
for (i in 0 until 1000) {
|
||||
list.add(FragmentedArrayFloatList(1).apply { add(i.toFloat() * 2.0f) })
|
||||
}
|
||||
assertEquals(1000, list.size)
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1000) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fragmentedArray() {
|
||||
val list = create(120)
|
||||
list.add(FloatArray(110) { it.toFloat() * 2 })
|
||||
list.add(FloatArray(50) { 220 + it.toFloat() * 2 })
|
||||
list.add(320.0f)
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 161) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fragmentedBuffer() {
|
||||
val list = create(120)
|
||||
list.add(wrap(*FloatArray(110) { it.toFloat() * 2 }))
|
||||
list.add(wrap(*FloatArray(50) { 220 + it.toFloat() * 2 }))
|
||||
list.add(320.0f)
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 161) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fragmentedHeapList() {
|
||||
val list = create(120)
|
||||
list.add(HeapArrayFloatList().apply { add(FloatArray(110) { it.toFloat() * 2 }) })
|
||||
list.add(HeapArrayFloatList().apply { add(FloatArray(50) { 220 + it.toFloat() * 2 }) })
|
||||
list.add(320.0f)
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 161) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fragmentedBufferedList() {
|
||||
val list = create(120)
|
||||
list.add(BufferedArrayFloatList().apply { add(FloatArray(110) { it.toFloat() * 2 }) })
|
||||
list.add(BufferedArrayFloatList().apply { add(FloatArray(50) { 220 + it.toFloat() * 2 }) })
|
||||
list.add(320.0f)
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 161) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fragmentedFragmentedList() {
|
||||
val list = create(120)
|
||||
list.add(FragmentedArrayFloatList().apply { add(FloatArray(110) { it.toFloat() * 2 }) })
|
||||
list.add(FragmentedArrayFloatList().apply { add(FloatArray(50) { 220 + it.toFloat() * 2 }) })
|
||||
list.add(320.0f)
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 161) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fragmentedFragmentedList2() {
|
||||
val list = create(120)
|
||||
list.add(FragmentedArrayFloatList(10).apply { add(FloatArray(110) { it.toFloat() * 2 }) })
|
||||
list.add(FragmentedArrayFloatList(14).apply { add(FloatArray(50) { 220 + it.toFloat() * 2 }) })
|
||||
list.add(320.0f)
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 161) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun ensureSizeArray() {
|
||||
val list = create(120)
|
||||
list.add(0.0f)
|
||||
list.ensureSize(1000)
|
||||
list.ensureSize(2000)
|
||||
list.add(FloatArray(1000) { 2.0f + it.toFloat() * 2 })
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1001) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ensureSizeBuffer() {
|
||||
val list = create(120)
|
||||
list.add(0.0f)
|
||||
list.ensureSize(1000)
|
||||
list.ensureSize(2000)
|
||||
list.add(wrap(*FloatArray(1000) { 2.0f + it.toFloat() * 2 }))
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1001) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ensureSizeHeapList() {
|
||||
val list = create(120)
|
||||
list.add(0.0f)
|
||||
list.ensureSize(1000)
|
||||
list.ensureSize(2000)
|
||||
list.add(HeapArrayFloatList().apply { add(FloatArray(1000) { 2.0f + it.toFloat() * 2 }) })
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1001) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ensureSizeBufferedList() {
|
||||
val list = create(120)
|
||||
list.add(0.0f)
|
||||
list.ensureSize(1000)
|
||||
list.ensureSize(2000)
|
||||
list.add(BufferedArrayFloatList().apply { add(FloatArray(1000) { 2.0f + it.toFloat() * 2 }) })
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1001) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ensureSizeFragmentedList() {
|
||||
val list = create(120)
|
||||
list.add(0.0f)
|
||||
list.ensureSize(1000)
|
||||
list.ensureSize(2000)
|
||||
list.add(FragmentedArrayFloatList().apply { add(FloatArray(1000) { 2.0f + it.toFloat() * 2 }) })
|
||||
|
||||
val array = list.toArray()
|
||||
for (i in 0 until 1001) {
|
||||
assertEquals(array[i], i.toFloat() * 2.0f)
|
||||
}
|
||||
}
|
||||
|
||||
private fun wrap(vararg array: Float): FloatBuffer {
|
||||
val buffer = FloatBuffer.wrap(array)
|
||||
buffer.position(array.size)
|
||||
|
||||
return buffer
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
class BufferedFloatListTest : DirectFloatListTest() {
|
||||
|
||||
override fun create(initialSize: Int): AbstractFloatList {
|
||||
return BufferedArrayFloatList(initialSize)
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
abstract class DirectFloatListTest : AbstractFloatListTest() {
|
||||
@Test
|
||||
fun singleToBuffer() {
|
||||
val list = create()
|
||||
if (list !is DirectArrayFloatList) {
|
||||
return
|
||||
}
|
||||
list.add(189.0f)
|
||||
val buffer = list.toBuffer()
|
||||
Assertions.assertEquals(buffer.get(0), 189.0f)
|
||||
Assertions.assertEquals(buffer.position(), 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun multipleToBuffer() {
|
||||
val list = create()
|
||||
if (list !is DirectArrayFloatList) {
|
||||
return
|
||||
}
|
||||
list.add(189.0f)
|
||||
list.add(289.0f)
|
||||
val buffer = list.toBuffer()
|
||||
Assertions.assertEquals(buffer.get(0), 189.0f)
|
||||
Assertions.assertEquals(buffer.get(1), 289.0f)
|
||||
Assertions.assertEquals(buffer.position(), 2)
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class FragmentedFloatListTest : DirectFloatListTest() {
|
||||
|
||||
override fun create(initialSize: Int): AbstractFloatList {
|
||||
return FragmentedArrayFloatList(initialSize)
|
||||
}
|
||||
|
||||
|
||||
private fun AbstractFloatList.putMixed() {
|
||||
ensureSize(7)
|
||||
add(1.0f)
|
||||
add(2.0f)
|
||||
add(floatArrayOf(3.0f, 4.0f))
|
||||
add(5.0f)
|
||||
add(6.0f)
|
||||
add(floatArrayOf(7.0f))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMixed() {
|
||||
val list = FragmentedArrayFloatList(1000)
|
||||
for (i in 0 until 2000) {
|
||||
println(i)
|
||||
list.putMixed()
|
||||
}
|
||||
assertEquals(14000, list.size)
|
||||
assertEquals(14000, list.toArray().size)
|
||||
assertEquals(14, list.fragments.size)
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.util.collections.floats
|
||||
|
||||
class HeapFloatListTest : AbstractFloatListTest() {
|
||||
|
||||
override fun create(initialSize: Int): AbstractFloatList {
|
||||
return HeapArrayFloatList(initialSize)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user