rendering: improve cullfacing (2)

This commit is contained in:
Bixilon 2021-03-27 01:04:43 +01:00
parent 6cc781a724
commit bdfe1345fa
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
8 changed files with 50 additions and 65 deletions

View File

@ -12,7 +12,7 @@
*/
package de.bixilon.minosoft.data
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import glm_.vec2.Vec2i
import glm_.vec3.Vec3
@ -27,8 +27,6 @@ enum class Directions(val directionVector: Vec3i) {
EAST(Vec3i(1, 0, 0));
val floatDirectionVector = Vec3(directionVector)
val blockResolutionVector = directionVector * BlockModelElement.BLOCK_RESOLUTION
val blockResolutionVectorFloat = Vec3(blockResolutionVector)
lateinit var inverse: Directions
private set
@ -53,52 +51,41 @@ enum class Directions(val directionVector: Vec3i) {
/**
* @return the size of the face in this direction. null if the face is not touching the border (determinated by the block resolution)
*/
fun getFaceBorderSizes(start: Vec3, end: Vec3): FaceBorderSize? {
fun getFaceBorderSizes(start: Vec3, end: Vec3): FaceSize? {
// check if face is touching the border of a block
if (!isBlockResolutionBorder(start, end)) {
return null
}
return getFaceSize(start, end)
}
fun getFaceSize(start: Vec3, end: Vec3): FaceSize {
return when (this) {
DOWN -> {
if (start.y != 0.0f && end.y != 0.0f) {
null
} else {
FaceBorderSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z))
DOWN, UP -> {
FaceSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z))
}
NORTH, SOUTH -> {
FaceSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y))
}
UP -> {
if (start.y != BlockModelElement.BLOCK_RESOLUTION_FLOAT && end.y != BlockModelElement.BLOCK_RESOLUTION_FLOAT) {
null
} else {
FaceBorderSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z))
}
}
NORTH -> {
if (start.z != 0.0f && end.z != 0.0f) {
null
} else {
FaceBorderSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y))
}
}
SOUTH -> {
if (start.z != BlockModelElement.BLOCK_RESOLUTION_FLOAT && end.z != BlockModelElement.BLOCK_RESOLUTION_FLOAT) {
null
} else {
FaceBorderSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y))
}
}
WEST -> {
if (start.x != 0.0f && end.x != 0.0f) {
null
} else {
FaceBorderSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z))
}
}
EAST -> {
if (start.x != BlockModelElement.BLOCK_RESOLUTION_FLOAT && end.x != BlockModelElement.BLOCK_RESOLUTION_FLOAT) {
null
} else {
FaceBorderSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z))
EAST, WEST -> {
FaceSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z))
}
}
}
private fun isBlockResolutionBorder(start: Vec3, end: Vec3): Boolean {
return isCoordinateBorder(directionVector.x, start.x, end.x) || isCoordinateBorder(directionVector.y, start.y, end.y) || isCoordinateBorder(directionVector.z, start.z, end.z)
}
private fun isCoordinateBorder(directionValue: Int, start: Float, end: Float): Boolean {
if (directionValue == 1) {
return start == BlockModelElement.BLOCK_RESOLUTION_FLOAT || end == BlockModelElement.BLOCK_RESOLUTION_FLOAT
}
if (directionValue == -1) {
return start == 0.0f || end == 0.0f
}
return false
}

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.gui.rendering.chunk.models
import glm_.vec2.Vec2i
data class FaceBorderSize(
data class FaceSize(
val start: Vec2i = Vec2i(0, 0),
val end: Vec2i = Vec2i(16, 16),
)

View File

@ -13,10 +13,10 @@
package de.bixilon.minosoft.gui.rendering.chunk.models.loading
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.VecUtil.readUV
import glm_.Java.Companion.glm
import glm_.vec2.Vec2
import glm_.vec3.Vec3
@ -44,9 +44,7 @@ class BlockModelFace {
}
private fun calculateTexturePositions(data: JsonObject?, from: Vec3, to: Vec3, direction: Directions): MutableList<Vec2> {
val (textureTopLeft: Vec2, textureBottomRight: Vec2) = data?.get("uv")?.asJsonArray?.let {
readUV(it)
} ?: getTexturePositionsFromRegion(from, to, direction)
val (textureTopLeft: Vec2, textureBottomRight: Vec2) = data?.get("uv")?.asJsonArray?.readUV() ?: getTexturePositionsFromRegion(from, to, direction)
return mutableListOf(
uvToFloat(Vec2(textureTopLeft.x, textureTopLeft.y)),
uvToFloat(Vec2(textureTopLeft.x, textureBottomRight.y)),
@ -55,15 +53,12 @@ class BlockModelFace {
)
}
private fun readUV(data: JsonArray): Pair<Vec2, Vec2> {
return Pair(Vec2(data[0].asFloat, data[3].asFloat), Vec2(data[2].asFloat, data[1].asFloat))
}
private fun getTexturePositionsFromRegion(from: Vec3, to: Vec3, direction: Directions): Pair<Vec2, Vec2> {
// ToDo: Remove the duplicated code in Directions
return when (direction) {
Directions.EAST, Directions.WEST -> Pair(Vec2(from.z.toInt(), to.y.toInt()), Vec2(to.z.toInt(), from.y.toInt()))
Directions.UP, Directions.DOWN -> Pair(Vec2(from.x.toInt(), to.z.toInt()), Vec2(to.x.toInt(), from.z.toInt()))
Directions.NORTH, Directions.SOUTH -> Pair(Vec2(from.x.toInt(), to.y.toInt()), Vec2(to.x.toInt(), from.y.toInt()))
Directions.EAST, Directions.WEST -> Pair(Vec2(from.z.toInt(), to.y.toInt()), Vec2(to.z.toInt(), from.y.toInt()))
}
}

View File

@ -6,11 +6,11 @@ import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.textures.Texture
interface BlockRenderInterface {
val faceBorderSizes: Array<Array<FaceBorderSize>?> // direction indexed
val faceBorderSizes: Array<Array<FaceSize>?> // direction indexed
val transparentFaces: BooleanArray
fun render(blockState: BlockState, lightAccessor: LightAccessor, tintColor: RGBColor?, position: BlockPosition, meshCollection: ChunkMeshCollection, neighbourBlocks: Array<BlockState?>, world: World)

View File

@ -23,7 +23,7 @@ import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel
import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureTransparencies
@ -33,7 +33,7 @@ class BlockRenderer : BlockRenderInterface {
val textures: MutableMap<String, String> = mutableMapOf()
private val elements: MutableSet<ElementRenderer> = mutableSetOf()
private val textureMapping: MutableMap<String, Texture> = mutableMapOf()
override val faceBorderSizes: Array<Array<FaceBorderSize>?> = arrayOfNulls(Directions.DIRECTIONS.size)
override val faceBorderSizes: Array<Array<FaceSize>?> = arrayOfNulls(Directions.DIRECTIONS.size)
override val transparentFaces: BooleanArray = BooleanArray(Directions.DIRECTIONS.size)
constructor(data: JsonObject, parent: BlockModel) {
@ -64,7 +64,7 @@ class BlockRenderer : BlockRenderInterface {
for (direction in Directions.DIRECTIONS) {
var directionIsCullFace: Boolean? = null
var directionIsNotTransparent: Boolean? = null
var faceBorderSites: MutableList<FaceBorderSize> = mutableListOf()
var faceBorderSites: MutableList<FaceSize> = mutableListOf()
for (element in elements) {
if (element.isCullFace(direction)) {
directionIsCullFace = true
@ -98,11 +98,9 @@ class BlockRenderer : BlockRenderInterface {
return
}
for (direction in Directions.DIRECTIONS) {
val cullFace = cullFaces[direction.ordinal] != null
val invertedDirection = direction.inverse
var isNeighbourTransparent = false
var neighbourFaceSize: Array<FaceBorderSize>? = null
var neighbourFaceSize: Array<FaceSize>? = null
neighbourBlocks[direction.ordinal]?.getBlockRenderer(position + direction)?.let {
if (it.transparentFaces[invertedDirection.ordinal]) {
isNeighbourTransparent = true
@ -110,6 +108,8 @@ class BlockRenderer : BlockRenderInterface {
neighbourFaceSize = it.faceBorderSizes[invertedDirection.ordinal]
}
// ToDo: Should we preserve the cullface attribute? It seems to has no point here.
for (element in elements) {
var drawElementFace = true

View File

@ -22,7 +22,7 @@ import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.SectionArrayMesh
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace
@ -35,7 +35,7 @@ import glm_.vec2.Vec2
import glm_.vec3.Vec3
class ElementRenderer(parent: BlockModelElement, val rotation: Vec3, uvLock: Boolean, rescale: Boolean) {
val faceBorderSize: Array<FaceBorderSize?> = arrayOfNulls(Directions.DIRECTIONS.size)
val faceBorderSize: Array<FaceSize?> = arrayOfNulls(Directions.DIRECTIONS.size)
private val faces: MutableMap<Directions, BlockModelFace> = mutableMapOf()
private var transformedPositions: Array<Vec3> = parent.transformedPositions.clone()
private val directionMapping: HashBiMap<Directions, Directions> = HashBiMap.create()

View File

@ -9,7 +9,7 @@ import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace
import de.bixilon.minosoft.gui.rendering.textures.Texture
@ -25,7 +25,7 @@ class FluidRenderer(
private val flowingTextureName: String,
private val regex: String,
) : BlockRenderInterface {
override val faceBorderSizes: Array<Array<FaceBorderSize>?> = arrayOfNulls(Directions.DIRECTIONS.size)
override val faceBorderSizes: Array<Array<FaceSize>?> = arrayOfNulls(Directions.DIRECTIONS.size)
override val transparentFaces: BooleanArray = BooleanArray(Directions.DIRECTIONS.size)
private lateinit var stillTexture: Texture
private lateinit var flowingTexture: Texture

View File

@ -75,4 +75,7 @@ object VecUtil {
return false
}
fun JsonArray.readUV(): Pair<Vec2, Vec2> {
return Pair(Vec2(this[0].asFloat, this[3].asFloat), Vec2(this[2].asFloat, this[1].asFloat))
}
}