package me.eater.threedom.gl.vertex import me.eater.threedom.gl.vertex.VertexDataPoint.* import org.joml.* import java.nio.ByteBuffer import kotlin.reflect.KProperty import kotlin.reflect.KProperty1 abstract class VertexData() { private val items = linkedMapOf>>() private var offset = 0 val length get() = items.map { (_, v) -> v.component2().length }.sum() class VertexDataRegister(private val default: T, val provider: (default: T) -> VertexDataPoint) { operator fun provideDelegate(thisRef: VertexData, prop: KProperty<*>): VertexDataPoint { val delegate = provider(default) thisRef.items[prop.name] = thisRef.offset to delegate thisRef.offset += delegate.length return delegate } } fun int(value: Int = 0): VertexDataRegister = VertexDataRegister(value, ::SingleInt) fun double(value: Double = 0.0): VertexDataRegister = VertexDataRegister(value, ::SingleDouble) fun float(value: Float = 0f): VertexDataRegister = VertexDataRegister(value, ::SingleFloat) fun bool(value: Boolean = false): VertexDataRegister = VertexDataRegister(value, ::SingleBoolean) fun vec2(value: Vector2fc = Vector2f()): VertexDataRegister = VertexDataRegister(value, ::Vec2) fun vec3(value: Vector3fc = Vector3f()): VertexDataRegister = VertexDataRegister(value, ::Vec3) fun vec4(value: Vector4fc = Vector4f()): VertexDataRegister = VertexDataRegister(value, ::Vec4) fun mat3(value: Matrix3fc = Matrix3f()): VertexDataRegister = VertexDataRegister(value, ::Mat3) fun mat4(value: Matrix4fc = Matrix4f()): VertexDataRegister = VertexDataRegister(value, ::Mat4) fun getDataPoint(prop: KProperty1): VertexDataPoint<*>? = items[prop.name]?.component2() fun getOffset(prop: KProperty1): Int? = items[prop.name]?.component1() fun writeNonInterleaved(position: Int, size: Int, byteBuffer: ByteBuffer) { var offset = 0; for ((_, pair) in items) { val (_, item) = pair item.write(offset + (position * item.length), byteBuffer) offset += item.length * size } } fun write(position: Int, byteBuffer: ByteBuffer) { var pos = position for ((_, pair) in items) { val (_, item) = pair item.write(pos, byteBuffer) pos += item.length } } }