Chart smooth bends

This commit is contained in:
DBotThePony 2024-10-06 20:44:24 +07:00
parent d0e6ab2829
commit 1c3fc4e6e6
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 117 additions and 31 deletions

View File

@ -55,7 +55,12 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
var lastTick by syncher.decimal()
internal set
var displayChartOnBlock by syncher.int(0, setter = DelegateSetter { field, value -> if (value in 0 .. charts.size + 1) field.accept(value) })
var displayChartOnBlock by syncher.int(0, setter = DelegateSetter { field, value ->
if (value in 0 .. charts.size + 1) {
field.accept(value)
markDirtyFast()
}
})
var ioLimit: Decimal? = null
@ -266,13 +271,6 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
thisTick = Decimal.ZERO
}
fun clientTick() {
// TODO
// historyTick = (historyTick + 1) % history.size
// history[historyTick] = lastTick
// passed += lastTick
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.energy_counter")
const val PASSED_ENERGY_KEY = "passedEnergy"

View File

@ -46,12 +46,9 @@ class EnergyCounterBlock(val color: DyeColor?) : MatteryBlock(DEFAULT_MACHINE_PR
blockState: BlockState,
blockEntityType: BlockEntityType<T>
): BlockEntityTicker<T>? {
if (blockEntityType !== MBlockEntities.ENERGY_COUNTER)
if (blockEntityType !== MBlockEntities.ENERGY_COUNTER || level.isClientSide)
return null
if (level.isClientSide)
return BlockEntityTicker { _, _, _, tile -> if (tile is EnergyCounterBlockEntity) tile.clientTick() }
return BlockEntityTicker { _, _, _, tile -> if (tile is EnergyCounterBlockEntity) tile.tick() }
}

View File

@ -4,6 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.ByteBufferBuilder
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexConsumer
import com.mojang.blaze3d.vertex.VertexFormat
import com.mojang.blaze3d.vertex.VertexSorting
import net.minecraft.client.gui.Font
@ -106,9 +107,35 @@ val CHART_RENDER_TYPE = run {
) as RenderType
}
val CHART_RENDER_TYPE2 = run {
val builder = RenderType.CompositeState.builder()
builder.setShaderState(RenderStateShard.ShaderStateShard(GameRenderer::getPositionColorShader))
builder.setDepthTestState(RenderStateShard.DepthTestStateShard("always", GL_LESS))
builder.setTransparencyState(RenderStateShard.TransparencyStateShard("normal_blend", {
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
}, { RenderSystem.disableBlend() }))
@Suppress("INACCESSIBLE_TYPE")
RenderType.create(
"otm_chart2",
DefaultVertexFormat.POSITION_COLOR,
VertexFormat.Mode.TRIANGLES,
16_000,
false,
true,
builder.createCompositeState(false)
) as RenderType
}
private val buffer = DynamicBufferSource(vertexSorting = VertexSorting.ORTHOGRAPHIC_Z)
private fun buffer() = buffer
private val sinValues = FloatArray(16) { sin(it / 16f * PI.toFloat() * 2f) }
private val cosValues = FloatArray(16) { cos(it / 16f * PI.toFloat() * 2f) }
fun renderChart(
poseStack: PoseStack,
charts: List<Pair<FloatArray, RGBAColor>>,
@ -125,6 +152,8 @@ fun renderChart(
require(charts.all { it.first.size == charts[0].first.size }) { "Provided chart data is not of same width" }
val builder = buffer.getBuffer(CHART_RENDER_TYPE)
val step = width / charts[0].first.size
// so we can work with crumbling buffer sources
val bendFuncs = ArrayList<VertexConsumer.() -> Unit>()
val checkLabels = labels != null && labels.mouseY in 0f .. height && labels.mouseX in 0f .. width
@ -134,20 +163,24 @@ fun renderChart(
var drawPointX = 0f
var drawPointY = 0f
val halfWidth = lineWidth / 2f
if (levelLabels != null) {
for ((level, label) in levelLabels.labels) {
val y0 = y + (1f - level) * height
builder.vertex(poseStack, x + width, lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
builder.vertex(poseStack, x + width, -lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
builder.vertex(poseStack, x, -lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
builder.vertex(poseStack, x, lineWidth / 2f + y0, 0f).color(levelLabels.lineColor)
builder.vertex(poseStack, x + width, halfWidth + y0, 0f).color(levelLabels.lineColor)
builder.vertex(poseStack, x + width, -halfWidth + y0, 0f).color(levelLabels.lineColor)
builder.vertex(poseStack, x, -halfWidth + y0, 0f).color(levelLabels.lineColor)
builder.vertex(poseStack, x, halfWidth + y0, 0f).color(levelLabels.lineColor)
}
}
poseStack.translate(0f, 0f, 0.2f)
for ((normalized, color) in charts) {
var previousAngle = 0f
for (i in 0 until normalized.size - 1) {
val y0 = y + (1f - normalized[i]) * height
val y1 = y + (1f - normalized[i + 1]) * height
@ -158,17 +191,22 @@ fun renderChart(
val xDiff = x1 - x0
val yDiff = y1 - y0
val currentAngle: Float
if (yDiff.sign == 0f) {
builder.vertex(poseStack, x0, y0 + lineWidth / 2f, 0f).color(color)
builder.vertex(poseStack, x0, y0 - lineWidth / 2f, 0f).color(color)
builder.vertex(poseStack, x1, y1 - lineWidth / 2f, 0f).color(color)
builder.vertex(poseStack, x1, y1 + lineWidth / 2f, 0f).color(color)
builder.vertex(poseStack, x0, y0 + halfWidth, 0f).color(color)
builder.vertex(poseStack, x0, y0 - halfWidth, 0f).color(color)
builder.vertex(poseStack, x1, y1 - halfWidth, 0f).color(color)
builder.vertex(poseStack, x1, y1 + halfWidth, 0f).color(color)
currentAngle = PI.toFloat() / 2f
} else {
val length = (xDiff.pow(2f) + yDiff.pow(2f)).pow(0.5f)
val angle = acos(xDiff / length) * yDiff.sign - PI / 2f // rotate 90 deg
val angle = acos(xDiff / length) * yDiff.sign - PI.toFloat() / 2f // rotate 90 deg
currentAngle = angle
val xDisp = cos(angle).toFloat() * lineWidth / 2f
val yDisp = sin(angle).toFloat() * lineWidth / 2f
val xDisp = cos(angle) * halfWidth
val yDisp = sin(angle) * halfWidth
builder.vertex(poseStack, x0 + xDisp, y0 + yDisp, 0f).color(color)
builder.vertex(poseStack, x0 - xDisp, y0 - yDisp, 0f).color(color)
@ -176,7 +214,60 @@ fun renderChart(
builder.vertex(poseStack, x1 + xDisp, y1 + yDisp, 0f).color(color)
}
//graphics.renderRect(x0, y0, LINE_WIDTH, LINE_WIDTH)
if (currentAngle != previousAngle) {
for (i2 in sinValues.indices) {
val i3 = (i2 + 1) % cosValues.size
val cos0 = cosValues[i2] * halfWidth
val cos1 = cosValues[i3] * halfWidth
val sin0 = sinValues[i2] * halfWidth
val sin1 = sinValues[i3] * halfWidth
bendFuncs.add {
vertex(poseStack, x0 + cos0, y0 + sin0, 0f).color(color)
vertex(poseStack, x0, y0, 0f).color(color)
vertex(poseStack, x0 + cos1, y0 + sin1, 0f).color(color)
}
}
}
// TODO: actually make this work, because this should be more efficient than drawing full circle
/*
if (previousAngle < currentAngle) {
// peak bend
var bendAngle = previousAngle - 0.05f
while (bendAngle < currentAngle + 0.05f) {
val sin0 = sin(bendAngle)
val cos0 = cos(bendAngle)
val sin1 = sin(bendAngle + 0.05f)
val cos1 = cos(bendAngle + 0.05f)
builder2.vertex(poseStack, x0 + cos0, y0 + sin0, 0f).color(color)
builder2.vertex(poseStack, x0, y0, 0f).color(color)
builder2.vertex(poseStack, x0 + cos1, y0 + sin1, 0f).color(color)
bendAngle += 0.05f
}
} else if (previousAngle > currentAngle) {
// chasm bend
var bendAngle = currentAngle - 0.05f
while (bendAngle < previousAngle + 0.05f) {
val sin0 = sin(bendAngle)
val cos0 = cos(bendAngle)
val sin1 = sin(bendAngle + 0.05f)
val cos1 = cos(bendAngle + 0.05f)
builder2.vertex(poseStack, x0 + cos0, y0 + sin0, 0f).color(color)
builder2.vertex(poseStack, x0, y0, 0f).color(color)
builder2.vertex(poseStack, x0 + cos1, y0 + sin1, 0f).color(color)
bendAngle += 0.05f
}
}
*/
previousAngle = currentAngle
if (checkLabels && drawLabel == -1 && labels!!.mouseX in x1 .. x0) {
drawLabel = i
@ -186,6 +277,11 @@ fun renderChart(
}
}
if (bendFuncs.isNotEmpty()) {
val builder2 = buffer.getBuffer(CHART_RENDER_TYPE2)
bendFuncs.forEach { it.invoke(builder2) }
}
if (levelLabels != null && levelLabels.labels.isNotEmpty()) {
poseStack.translate(0f, 0f, 0.2f)
val font = levelLabels.font ?: minecraft.font

View File

@ -165,6 +165,7 @@ class DynamicBufferSource(
next = State(Sheets.chestSheet(), ImmutableList.of(next.type), immutableAfter = true, chained = false)
next = State(CHART_RENDER_TYPE, ImmutableList.of(next.type), immutableAfter = true, chained = true)
next = State(CHART_RENDER_TYPE2, ImmutableList.of(next.type), immutableAfter = true, chained = true)
next = State(rectRenderType(true, false, true), ImmutableList.of(next.type), immutableAfter = true, chained = true)
next = State(rectRenderType(true, false, false), ImmutableList.of(next.type), immutableAfter = true, chained = true)
@ -250,13 +251,7 @@ class DynamicBufferSource(
}
override fun getBuffer(renderType: RenderType): VertexConsumer {
var getState = buffers[renderType]
if (getState == null) {
getState = State(renderType)
}
return getState.begin()
return (buffers[renderType] ?: State(renderType)).begin()
}
fun getBuffer(renderType: RenderType, after: RenderType): VertexConsumer {