[WIP] Cactus, netherrack, round logs work
+ lots more cleanup + Optifine x-ray fix
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
package mods.betterfoliage.render.column
|
||||
|
||||
import mods.betterfoliage.config.Config
|
||||
import mods.betterfoliage.model.Quad
|
||||
import mods.betterfoliage.model.UV
|
||||
import mods.betterfoliage.model.Vertex
|
||||
import mods.betterfoliage.model.bake
|
||||
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType
|
||||
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType.INVISIBLE
|
||||
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType.LARGE_RADIUS
|
||||
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType.SMALL_RADIUS
|
||||
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType.SQUARE
|
||||
import mods.betterfoliage.util.Double3
|
||||
import mods.betterfoliage.util.Rotation
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.util.Direction.Axis
|
||||
import net.minecraft.util.Direction.EAST
|
||||
import net.minecraft.util.Direction.SOUTH
|
||||
import net.minecraft.util.Direction.UP
|
||||
|
||||
/**
|
||||
* Collection of dynamically generated meshes used to render rounded columns.
|
||||
*/
|
||||
class ColumnMeshSet(
|
||||
radiusSmall: Double,
|
||||
radiusLarge: Double,
|
||||
zProtection: Double,
|
||||
val axis: Axis,
|
||||
val spriteLeft: TextureAtlasSprite,
|
||||
val spriteRight: TextureAtlasSprite,
|
||||
val spriteTop: TextureAtlasSprite,
|
||||
val spriteBottom: TextureAtlasSprite
|
||||
) {
|
||||
protected fun sideRounded(radius: Double, yBottom: Double, yTop: Double): List<Quad> {
|
||||
val halfRadius = radius * 0.5
|
||||
return listOf(
|
||||
// left side of the diagonal
|
||||
Quad.verticalRectangle(0.0, 0.5, 0.5 - radius, 0.5, yBottom, yTop).clampUV(minU = 0.0, maxU = 0.5 - radius),
|
||||
Quad.verticalRectangle(0.5 - radius, 0.5, 0.5 - halfRadius, 0.5 - halfRadius, yBottom, yTop).clampUV(minU = 0.5 - radius),
|
||||
// right side of the diagonal
|
||||
Quad.verticalRectangle(0.5 - halfRadius, 0.5 - halfRadius, 0.5, 0.5 - radius, yBottom, yTop).clampUV(maxU = radius - 0.5),
|
||||
Quad.verticalRectangle(0.5, 0.5 - radius, 0.5, 0.0, yBottom, yTop).clampUV(minU = radius - 0.5, maxU = 0.0)
|
||||
)
|
||||
}
|
||||
|
||||
protected fun sideRoundedTransition(radiusBottom: Double, radiusTop: Double, yBottom: Double, yTop: Double): List<Quad> {
|
||||
val ySplit = 0.5 * (yBottom + yTop)
|
||||
val modelTop = sideRounded(radiusTop, yBottom, yTop)
|
||||
val modelBottom = sideRounded(radiusBottom, yBottom, yTop)
|
||||
return (modelBottom zip modelTop).map { (quadBottom, quadTop) ->
|
||||
Quad.mix(quadBottom, quadTop) { vBottom, vTop -> if (vBottom.xyz.y < ySplit) vBottom.copy() else vTop.copy() }
|
||||
}
|
||||
}
|
||||
|
||||
protected fun sideSquare(yBottom: Double, yTop: Double) = listOf(
|
||||
Quad.verticalRectangle(0.0, 0.5, 0.5, 0.5, yBottom, yTop).clampUV(minU = 0.0),
|
||||
Quad.verticalRectangle(0.5, 0.5, 0.5, 0.0, yBottom, yTop).clampUV(maxU = 0.0)
|
||||
)
|
||||
|
||||
protected fun lidRounded(radius: Double, y: Double, isBottom: Boolean) = Array(4) { quadrant ->
|
||||
val rotation = baseRotation(axis) + quadrantRotations[quadrant]
|
||||
val v1 = Vertex(Double3(0.0, y, 0.0), UV(0.0, 0.0))
|
||||
val v2 = Vertex(Double3(0.0, y, 0.5), UV(0.0, 0.5))
|
||||
val v3 = Vertex(Double3(0.5 - radius, y, 0.5), UV(0.5 - radius, 0.5))
|
||||
val v4 = Vertex(Double3(0.5 - radius * 0.5, y, 0.5 - radius * 0.5), UV(0.5, 0.5))
|
||||
val v5 = Vertex(Double3(0.5, y, 0.5 - radius), UV(0.5, 0.5 - radius))
|
||||
val v6 = Vertex(Double3(0.5, y, 0.0), UV(0.5, 0.0))
|
||||
listOf(Quad(v1, v2, v3, v4), Quad(v1, v4, v5, v6))
|
||||
.map { it.cycleVertices(if (isBottom xor Config.nVidia) 0 else 1) }
|
||||
.map { it.rotate(rotation).rotateUV(quadrant) }
|
||||
.map { it.sprite(if (isBottom) spriteBottom else spriteTop) }
|
||||
.map { if (isBottom) it.flipped else it }
|
||||
}
|
||||
|
||||
protected fun lidSquare(y: Double, isBottom: Boolean) = Array(4) { quadrant ->
|
||||
val rotation = baseRotation(axis) + quadrantRotations[quadrant]
|
||||
listOf(
|
||||
Quad.horizontalRectangle(x1 = 0.0, x2 = 0.5, z1 = 0.0, z2 = 0.5, y = y).clampUV(minU = 0.0, minV = 0.0)
|
||||
.rotate(rotation).rotateUV(quadrant)
|
||||
.sprite(if (isBottom) spriteBottom else spriteTop)
|
||||
.let { if (isBottom) it.flipped else it }
|
||||
)
|
||||
}
|
||||
|
||||
protected val zProtectionScale = zProtection.let { Double3(it, 1.0, it) }
|
||||
|
||||
protected fun List<Quad>.extendTop(size: Double) = map { q -> q.clampUV(minV = 0.5 - size).transformV { v ->
|
||||
if (v.xyz.y > 0.501) v.copy(xyz = v.xyz * zProtectionScale) else v }
|
||||
}
|
||||
protected fun List<Quad>.extendBottom(size: Double) = map { q -> q.clampUV(maxV = -0.5 + size).transformV { v ->
|
||||
if (v.xyz.y < -0.501) v.copy(xyz = v.xyz * zProtectionScale) else v }
|
||||
}
|
||||
protected fun List<Quad>.buildSides(quadsPerSprite: Int) = Array(4) { quadrant ->
|
||||
val rotation = baseRotation(axis) + quadrantRotations[quadrant]
|
||||
this.map { it.rotate(rotation) }
|
||||
.mapIndexed { idx, q -> if (idx % (2 * quadsPerSprite) >= quadsPerSprite) q.sprite(spriteRight) else q.sprite(spriteLeft) }
|
||||
.bake(false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun baseRotation(axis: Axis) = when(axis) {
|
||||
Axis.X -> Rotation.fromUp[EAST.ordinal]
|
||||
Axis.Y -> Rotation.fromUp[UP.ordinal]
|
||||
Axis.Z -> Rotation.fromUp[SOUTH.ordinal]
|
||||
}
|
||||
val quadrantRotations = Array(4) { Rotation.rot90[UP.ordinal] * it }
|
||||
}
|
||||
|
||||
//
|
||||
// Mesh definitions
|
||||
// 4-element arrays hold prebuild meshes for each of the rotations around the axis
|
||||
//
|
||||
val sideSquare = sideSquare(-0.5, 0.5).buildSides(quadsPerSprite = 1)
|
||||
val sideRoundSmall = sideRounded(radiusSmall, -0.5, 0.5).buildSides(quadsPerSprite = 2)
|
||||
val sideRoundLarge = sideRounded(radiusLarge, -0.5, 0.5).buildSides(quadsPerSprite = 2)
|
||||
|
||||
val sideExtendTopSquare = sideSquare(0.5, 0.5 + radiusLarge).extendTop(radiusLarge).buildSides(quadsPerSprite = 1)
|
||||
val sideExtendTopRoundSmall = sideRounded(radiusSmall, 0.5, 0.5 + radiusLarge).extendTop(radiusLarge).buildSides(quadsPerSprite = 2)
|
||||
val sideExtendTopRoundLarge = sideRounded(radiusLarge, 0.5, 0.5 + radiusLarge).extendTop(radiusLarge).buildSides(quadsPerSprite = 2)
|
||||
|
||||
val sideExtendBottomSquare = sideSquare(-0.5 - radiusLarge, -0.5).extendBottom(radiusLarge).buildSides(quadsPerSprite = 1)
|
||||
val sideExtendBottomRoundSmall = sideRounded(radiusSmall, -0.5 - radiusLarge, -0.5).extendBottom(radiusLarge).buildSides(quadsPerSprite = 2)
|
||||
val sideExtendBottomRoundLarge = sideRounded(radiusLarge, -0.5 - radiusLarge, -0.5).extendBottom(radiusLarge).buildSides(quadsPerSprite = 2)
|
||||
|
||||
val lidTopSquare = lidSquare(0.5, false).bake(false)
|
||||
val lidTopRoundSmall = lidRounded(radiusSmall, 0.5, false).bake(false)
|
||||
val lidTopRoundLarge = lidRounded(radiusLarge, 0.5, false).bake(false)
|
||||
|
||||
val lidBottomSquare = lidSquare(-0.5, true).bake(false)
|
||||
val lidBottomRoundSmall = lidRounded(radiusSmall, -0.5, true).bake(false)
|
||||
val lidBottomRoundLarge = lidRounded(radiusLarge, -0.5, true).bake(false)
|
||||
|
||||
val transitionTop = sideRoundedTransition(radiusLarge, radiusSmall, -0.5, 0.5).buildSides(quadsPerSprite = 2)
|
||||
val transitionBottom = sideRoundedTransition(radiusSmall, radiusLarge, -0.5, 0.5).buildSides(quadsPerSprite = 2)
|
||||
|
||||
//
|
||||
// Helper fuctions for lids (block ends)
|
||||
//
|
||||
fun flatTop(quadrantTypes: Array<QuadrantType>, quadrant: Int) = when(quadrantTypes[quadrant]) {
|
||||
SMALL_RADIUS -> lidTopRoundSmall[quadrant]
|
||||
LARGE_RADIUS -> lidTopRoundLarge[quadrant]
|
||||
SQUARE -> lidTopSquare[quadrant]
|
||||
INVISIBLE -> lidTopSquare[quadrant]
|
||||
}
|
||||
|
||||
fun flatBottom(quadrantTypes: Array<QuadrantType>, quadrant: Int) = when(quadrantTypes[quadrant]) {
|
||||
SMALL_RADIUS -> lidBottomRoundSmall[quadrant]
|
||||
LARGE_RADIUS -> lidBottomRoundLarge[quadrant]
|
||||
SQUARE -> lidBottomSquare[quadrant]
|
||||
INVISIBLE -> lidBottomSquare[quadrant]
|
||||
}
|
||||
|
||||
fun extendTop(quadrantTypes: Array<QuadrantType>, quadrant: Int) = when(quadrantTypes[quadrant]) {
|
||||
SMALL_RADIUS -> sideExtendTopRoundSmall[quadrant]
|
||||
LARGE_RADIUS -> sideExtendTopRoundLarge[quadrant]
|
||||
SQUARE -> sideExtendTopSquare[quadrant]
|
||||
INVISIBLE -> sideExtendTopSquare[quadrant]
|
||||
}
|
||||
|
||||
fun extendBottom(quadrantTypes: Array<QuadrantType>, quadrant: Int) = when(quadrantTypes[quadrant]) {
|
||||
SMALL_RADIUS -> sideExtendBottomRoundSmall[quadrant]
|
||||
LARGE_RADIUS -> sideExtendBottomRoundLarge[quadrant]
|
||||
SQUARE -> sideExtendBottomSquare[quadrant]
|
||||
INVISIBLE -> sideExtendBottomSquare[quadrant]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user