diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt index 1caa97515..d4e1f40e4 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020 Moritz Zwerger + * Copyright (C) 2020 Moritz Zwerger, Lukas Eisenhauer * * 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. * @@ -15,7 +15,6 @@ package de.bixilon.minosoft.data.mappings.blocks import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.data.mappings.ModIdentifier import de.bixilon.minosoft.data.world.BlockPosition -import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.BlockRenderer import java.util.* import kotlin.random.Random @@ -23,7 +22,6 @@ import kotlin.random.Random data class Block(val identifier: ModIdentifier) { var rotation: BlockRotations = BlockRotations.NONE var properties: Set = setOf() - val blockModels: MutableList = mutableListOf() val blockRenderers: MutableList = mutableListOf() constructor(identifier: ModIdentifier, properties: Set, rotation: BlockRotations) : this(identifier) { diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt b/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt index 7b5a7c01e..661d06507 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt @@ -56,7 +56,7 @@ class VersionMapping(var version: Version?) { private val dimensionIdMap = HashBiMap.create() var dimensionIdentifierMap: HashBiMap = HashBiMap.create() - val blockIdMap = HashBiMap.create(20000) + val blockIdMap: HashBiMap = HashBiMap.create(20000) private val entityInformationMap = HashBiMap.create, EntityInformation>(120) private val entityMetaIndexMap = HashMap(180) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockCondition.java b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockCondition.java deleted file mode 100644 index 1f8585fc5..000000000 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockCondition.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.bixilon.minosoft.gui.rendering.chunk.models.loading; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import de.bixilon.minosoft.data.mappings.blocks.Block; -import de.bixilon.minosoft.data.mappings.blocks.BlockProperties; -import de.bixilon.minosoft.data.mappings.blocks.BlockRotations; - -import java.util.HashSet; -import java.util.Map; - -public class BlockCondition { - public static final BlockCondition TRUE_CONDITION = new BlockCondition() { - @Override - public boolean contains(Block block) { - return true; - } - }; - - private HashSet properties; - private BlockRotations rotation; - - public BlockCondition(JsonObject json) { - properties = new HashSet<>(); - rotation = BlockRotations.NONE; - for (Map.Entry entry : json.entrySet()) { - String value = entry.getValue().getAsString(); - if (BlockProperties.PROPERTIES_MAPPING.containsKey(entry.getKey())) { - properties.add(BlockProperties.PROPERTIES_MAPPING.get(entry.getKey()).get(value)); - continue; - } - rotation = BlockRotations.ROTATION_MAPPING.get(value); - } - } - - public BlockCondition() { - } - - public boolean contains(Block block) { - if (rotation != BlockRotations.NONE && rotation != block.getRotation()) { - return false; - } - return block.getProperties().containsAll(properties); - } -} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockCondition.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockCondition.kt new file mode 100644 index 000000000..0f5fb219e --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockCondition.kt @@ -0,0 +1,58 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger, Lukas Eisenhauer + * + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.chunk.models.loading + +import com.google.gson.JsonObject +import de.bixilon.minosoft.data.mappings.blocks.Block +import de.bixilon.minosoft.data.mappings.blocks.BlockProperties +import de.bixilon.minosoft.data.mappings.blocks.BlockRotations + +open class BlockCondition { + private var properties: MutableSet = mutableSetOf() + private var rotation: BlockRotations = BlockRotations.NONE + + constructor(json: JsonObject) { + for ((key, value) in json.entrySet()) { + val value = value.asString + kotlin.run { + BlockRotations.ROTATION_MAPPING[value]?.let { + rotation = it + return@run + } + + BlockProperties.PROPERTIES_MAPPING[key]?.get(value)?.let { + properties.add(it) + } + } + } + } + + constructor() + + open operator fun contains(block: Block): Boolean { + return if (rotation != BlockRotations.NONE && rotation != block.rotation) { + false + } else { + block.properties.containsAll(properties) + } + } + + companion object { + val TRUE_CONDITION: BlockCondition = object : BlockCondition() { + override fun contains(block: Block): Boolean { + return true + } + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModel.kt index 410f8feb4..a15589179 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModel.kt @@ -14,17 +14,13 @@ package de.bixilon.minosoft.gui.rendering.chunk.models.loading import com.google.gson.JsonObject -import de.bixilon.minosoft.data.Directions -import de.bixilon.minosoft.gui.rendering.textures.Texture import glm_.glm import glm_.vec3.Vec3 open class BlockModel(val parent: BlockModel? = null, json: JsonObject) { val textures: MutableMap = parent?.textures?.toMutableMap() ?: mutableMapOf() - private val textureMapping: MutableMap = mutableMapOf() var elements: MutableList = parent?.elements?.toMutableList() ?: mutableListOf() - val fullFaceDirections: MutableSet = parent?.fullFaceDirections?.toMutableSet() ?: mutableSetOf() - private var rotation: Vec3 + var rotation: Vec3 private var uvLock = false // ToDo private var rescale = false // ToDo @@ -41,11 +37,9 @@ open class BlockModel(val parent: BlockModel? = null, json: JsonObject) { } json["elements"]?.let { it -> elements.clear() - fullFaceDirections.clear() for (element in it.asJsonArray) { val blockModelElement = BlockModelElement(element.asJsonObject) elements.add(blockModelElement) - fullFaceDirections.addAll(blockModelElement.fullFaceDirections) } } var rotateX = parent?.rotation?.x ?: 0f @@ -69,7 +63,6 @@ open class BlockModel(val parent: BlockModel? = null, json: JsonObject) { rotation = glm.radians(Vec3(rotateX, rotateY, rotateZ)) } - private fun getTextureByType(type: String): String { var currentValue: String = type while (currentValue.startsWith("#")) { @@ -82,23 +75,4 @@ open class BlockModel(val parent: BlockModel? = null, json: JsonObject) { } return currentValue } - - fun isCullFace(direction: Directions): Boolean { - for (element in elements) { - if (element.isCullFace(direction)) { - return true - } - } - return false - } - - fun isTransparent(direction: Directions): Boolean { - for (element in elements) { - if (textureMapping[element.getTexture(direction)]?.isTransparent == true) { - return true - } - } - return false - - } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelElement.kt index 2d585f10a..9a31b33c7 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelElement.kt @@ -1,3 +1,16 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger, Lukas Eisenhauer + * + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + package de.bixilon.minosoft.gui.rendering.chunk.models.loading import com.google.gson.JsonArray @@ -9,13 +22,11 @@ import glm_.vec3.Vec3 open class BlockModelElement(data: JsonObject) { val faces: MutableMap = mutableMapOf() - val fullFaceDirections: MutableSet = mutableSetOf() - var fullFace = false var positions: Array init { var from = Vec3(0, 0, 0) - var to = Vec3(16, 16, 16) + var to = Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, BLOCK_RESOLUTION) data["from"]?.let { val array = it.asJsonArray from = Vec3(array[0].asFloat, array[1].asFloat, array[2].asFloat) @@ -26,35 +37,24 @@ open class BlockModelElement(data: JsonObject) { } positions = arrayOf( Vec3(from), - Vec3(to.x, from.y, from.z), - Vec3(from.x, from.y, to.z), - Vec3(to.x, from.y, to.z), - Vec3(from.x, to.y, from.z), - Vec3(to.x, to.y, from.z), - Vec3(from.x, to.y, to.z), + Vec3(to.x, from.y, from.z), + Vec3(from.x, from.y, to.z), + Vec3(to.x, from.y, to.z), + Vec3(from.x, to.y, from.z), + Vec3(to.x, to.y, from.z), + Vec3(from.x, to.y, to.z), Vec3(to), - ) - var rotate = Vec3() + ) data["rotation"]?.let { val rotation = it.asJsonObject val axis = Axes.valueOf(rotation["axis"].asString.toUpperCase()) val angle = glm.radians(rotation["angle"].asDouble) rotatePositions(positions, axis, angle, jsonArrayToVec3(rotation["origin"].asJsonArray)) - rotate = when (axis) { - Axes.X -> run { return@run Vec3(angle, 0, 0) } - Axes.Y -> run { return@run Vec3(0, angle, 0) } - Axes.Z -> run { return@run Vec3(0, 0, angle) } - } } data["faces"]?.let { for ((directionName, json) in it.asJsonObject.entrySet()) { - var direction = Directions.valueOf(directionName.toUpperCase()) + val direction = Directions.valueOf(directionName.toUpperCase()) faces[direction] = BlockModelFace(json.asJsonObject, from, to, direction) - direction = getRotatedDirection(rotate, direction) - fullFace = positions.containsAll(fullTestPositions[direction]) // TODO: check if texture is transparent ==> && ! texture.isTransparent - if (fullFace) { - fullFaceDirections.add(direction) - } } } for ((i, position) in positions.withIndex()) { @@ -62,19 +62,11 @@ open class BlockModelElement(data: JsonObject) { } } - fun isCullFace(direction: Directions): Boolean { - return faces[direction]?.cullFace == direction - } - - fun getTexture(direction: Directions): String? { - return faces[direction]?.textureName - } - companion object { - fun jsonArrayToVec3(array: JsonArray) : Vec3 { + fun jsonArrayToVec3(array: JsonArray): Vec3 { return Vec3(array[0].asFloat, array[1].asFloat, array[2].asFloat) } - private const val BLOCK_RESOLUTION = 16 + const val BLOCK_RESOLUTION = 16f val FACE_POSITION_MAP_TEMPLATE = arrayOf( intArrayOf(0, 2, 3, 1), @@ -83,52 +75,42 @@ open class BlockModelElement(data: JsonObject) { intArrayOf(2, 6, 7, 3), intArrayOf(6, 2, 0, 4), intArrayOf(5, 1, 3, 7) - ) + ) - private val POSITION_1 = Vec3(0, 0, 0) - private val POSITION_2 = Vec3(BLOCK_RESOLUTION, 0, 0) - private val POSITION_3 = Vec3(0, 0, BLOCK_RESOLUTION) - private val POSITION_4 = Vec3(BLOCK_RESOLUTION, 0, BLOCK_RESOLUTION) - - private val POSITION_5 = Vec3(0, BLOCK_RESOLUTION, 0) - private val POSITION_6 = Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, 0) - private val POSITION_7 = Vec3(0, BLOCK_RESOLUTION, BLOCK_RESOLUTION) - private val POSITION_8 = Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, BLOCK_RESOLUTION) + private val POSITION_1 = Vec3(-0.5f, -0.5f, -0.5f) // Vec3(0, 0, 0) + private val POSITION_2 = Vec3(+0.5f, -0.5f, -0.5f) // Vec3(BLOCK_RESOLUTION, 0, 0) + private val POSITION_3 = Vec3(-0.5f, -0.5f, +0.5f) // Vec3(0, 0, BLOCK_RESOLUTION) + private val POSITION_4 = Vec3(+0.5f, -0.5f, +0.5f) // Vec3(BLOCK_RESOLUTION, 0, BLOCK_RESOLUTION) + private val POSITION_5 = Vec3(-0.5f, +0.5f, -0.5f) // Vec3(0, BLOCK_RESOLUTION, 0) + private val POSITION_6 = Vec3(+0.5f, +0.5f, +0.5f) // Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, 0) + private val POSITION_7 = Vec3(-0.5f, +0.5f, +0.5f) // Vec3(0, BLOCK_RESOLUTION, BLOCK_RESOLUTION) + private val POSITION_8 = Vec3(+0.5f, +0.5f, +0.5f) // Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, BLOCK_RESOLUTION) val fullTestPositions = mapOf( - Pair(Directions.EAST, setOf(POSITION_1, POSITION_3, POSITION_5, POSITION_7)), - Pair(Directions.WEST, setOf(POSITION_2, POSITION_4, POSITION_6, POSITION_8)), - Pair(Directions.DOWN, setOf(POSITION_1, POSITION_2, POSITION_3, POSITION_4)), - Pair(Directions.UP, setOf(POSITION_5, POSITION_6, POSITION_7, POSITION_8)), - Pair(Directions.SOUTH, setOf(POSITION_1, POSITION_2, POSITION_5, POSITION_6)), - Pair(Directions.NORTH, setOf(POSITION_3, POSITION_4, POSITION_7, POSITION_8)), - ) + Directions.EAST to setOf(POSITION_1, POSITION_3, POSITION_5, POSITION_7), + Directions.WEST to setOf(POSITION_2, POSITION_4, POSITION_6, POSITION_8), + Directions.DOWN to setOf(POSITION_1, POSITION_2, POSITION_3, POSITION_4), + Directions.UP to setOf(POSITION_5, POSITION_6, POSITION_7, POSITION_8), + Directions.SOUTH to setOf(POSITION_1, POSITION_2, POSITION_5, POSITION_6), + Directions.NORTH to setOf(POSITION_3, POSITION_4, POSITION_7, POSITION_8), + ) - fun getRotatedDirection(rotation: Vec3, direction: Directions): Directions { - if (rotation == Vec3(0, 0, 0)) { - return direction - } - var rotatedDirectionVector = rotateVector(direction.directionVector, rotation.z.toDouble(), Axes.Z) - rotatedDirectionVector = rotateVector(rotatedDirectionVector, rotation.y.toDouble(), Axes.Y) - return Directions.byDirection(rotateVector(rotatedDirectionVector, rotation.x.toDouble(), Axes.X)) - } - - private fun rotateVector(original: Vec3, angle: Double, axis: Axes): Vec3 { + fun rotateVector(original: Vec3, angle: Double, axis: Axes): Vec3 { fun getRotatedValues(x: Float, y: Float, sin: Double, cos: Double): Pair { return Pair((x * cos - y * sin).toFloat(), (x * sin + y * cos).toFloat()) } return when (axis) { - Axes.X -> run { + Axes.X -> { val rotatedValues = getRotatedValues(original.y, original.z, glm.sin(angle), glm.cos(angle)) - return@run Vec3(original.x, rotatedValues.first, rotatedValues.second) + Vec3(original.x, rotatedValues.first, rotatedValues.second) } - Axes.Y -> run { + Axes.Y -> { val rotatedValues = getRotatedValues(original.x, original.z, glm.sin(angle), glm.cos(angle)) - return@run Vec3(rotatedValues.first, original.y, rotatedValues.second) + Vec3(rotatedValues.first, original.y, rotatedValues.second) } - Axes.Z -> run { + Axes.Z -> { val rotatedValues = getRotatedValues(original.x, original.y, glm.sin(angle), glm.cos(angle)) - return@run Vec3(rotatedValues.first, rotatedValues.second, original.z) + Vec3(rotatedValues.first, rotatedValues.second, original.z) } } } @@ -145,29 +127,11 @@ open class BlockModelElement(data: JsonObject) { } } - fun rotatePositionsAxes(positions: Array, angles: Vec3) { - rotatePositions(positions, Axes.Z, angles.z.toDouble(), Vec3()) - rotatePositions(positions, Axes.Y, angles.y.toDouble(), Vec3()) - rotatePositions(positions, Axes.X, angles.x.toDouble(), Vec3()) - } - fun transformPosition(position: Vec3): Vec3 { fun positionToFloat(uv: Float): Float { - return (uv - 8f) / 16f + return (uv - 8f) / BLOCK_RESOLUTION } return Vec3(positionToFloat(position.x), positionToFloat(position.y), positionToFloat(position.z)) } } } - -private fun Array.containsAll(set: Set?): Boolean { - if (set != null) { - for (value in set) { - if (! this.contains(value)) { - return false; - } - } - return true - } - return false -} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelFace.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelFace.kt index 927ca443e..978ed0353 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelFace.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/loading/BlockModelFace.kt @@ -1,3 +1,16 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger, Lukas Eisenhauer + * + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + package de.bixilon.minosoft.gui.rendering.chunk.models.loading import com.google.gson.JsonObject @@ -16,16 +29,16 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio var textureEnd = Vec2(16, 16) when (direction) { Directions.EAST, Directions.WEST -> run { - textureStart = Vec2(from.z.toInt(), 16 - from.y.toInt()); - textureEnd = Vec2(to.z.toInt(), 16 - to.y.toInt()); + textureStart = Vec2(from.z.toInt(), BlockModelElement.BLOCK_RESOLUTION - from.y.toInt()) + textureEnd = Vec2(to.z.toInt(), BlockModelElement.BLOCK_RESOLUTION - to.y.toInt()) } Directions.UP, Directions.DOWN -> { - textureStart = Vec2(from.x.toInt(), 16 - from.z.toInt()); - textureEnd = Vec2(to.x.toInt(), 16 - to.z.toInt()); + textureStart = Vec2(from.x.toInt(), BlockModelElement.BLOCK_RESOLUTION - from.z.toInt()) + textureEnd = Vec2(to.x.toInt(), BlockModelElement.BLOCK_RESOLUTION - to.z.toInt()) } Directions.NORTH, Directions.SOUTH -> { - textureStart = Vec2(from.x.toInt(), 16 - from.y.toInt()); - textureEnd = Vec2(to.x.toInt(), 16 - to.y.toInt()); + textureStart = Vec2(from.x.toInt(), BlockModelElement.BLOCK_RESOLUTION - from.y.toInt()) + textureEnd = Vec2(to.x.toInt(), BlockModelElement.BLOCK_RESOLUTION - to.y.toInt()) } } data["uv"]?.asJsonArray?.let { @@ -37,7 +50,7 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio uvToFloat(Vec2(textureStart.x, textureEnd.y)), uvToFloat(Vec2(textureEnd.x, textureEnd.y)), uvToFloat(Vec2(textureEnd.x, textureStart.y)), - ) + ) cullFace = data["cullface"]?.asString?.let { return@let if (it == "bottom") { @@ -51,7 +64,7 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio Vec2(uvToFloat(textureStart.x), uvToFloat(textureEnd.y)), Vec2(uvToFloat(textureEnd.x), uvToFloat(textureEnd.y)), Vec2(uvToFloat(textureEnd.x), uvToFloat(textureStart.y)), - ) + ) } fun getTexturePositionArray(direction: Directions): Array { @@ -66,7 +79,7 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio companion object { private fun uvToFloat(uv: Float): Float { - return (uv) / 16f + return (uv) / BlockModelElement.BLOCK_RESOLUTION } fun uvToFloat(vec2: Vec2): Vec2 { @@ -74,12 +87,12 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio } val textureTemplate = arrayOf( - arrayOf(0, 1, 2, 3, ), - arrayOf(0, 1, 2, 3, ), - arrayOf(3, 2, 1, 0, ), - arrayOf(0, 1, 2, 3, ), - arrayOf(2, 3, 0, 1, ), - arrayOf(1, 0, 3, 2, ), - ) + arrayOf(0, 1, 2, 3), + arrayOf(0, 1, 2, 3), + arrayOf(3, 2, 1, 0), + arrayOf(0, 1, 2, 3), + arrayOf(2, 3, 0, 1), + arrayOf(1, 0, 3, 2), + ) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt index 16f252187..b059731d8 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt @@ -1,3 +1,16 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger, Lukas Eisenhauer + * + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + package de.bixilon.minosoft.gui.rendering.chunk.models.renderable import com.google.gson.JsonObject @@ -9,24 +22,26 @@ import de.bixilon.minosoft.gui.rendering.textures.Texture import glm_.mat4x4.Mat4 import glm_.vec3.Vec3 -class BlockRenderer() { +class BlockRenderer { + private val transparentFaces: MutableSet = mutableSetOf() + private val cullFaces: MutableSet = mutableSetOf() val textures: MutableMap = mutableMapOf() private val fullFaceDirections: MutableSet = mutableSetOf() private val elements: MutableSet = mutableSetOf() - private val rotation: Vec3 = Vec3() private val textureMapping: MutableMap = mutableMapOf() - constructor(entry: JsonObject, mapping: VersionMapping) : this() { + constructor(entry: JsonObject, mapping: VersionMapping) { loadElements(entry, mapping) } private fun loadElements(entry: JsonObject, mapping: VersionMapping) { - this.elements.addAll(ElementRenderer.createElements(entry, mapping)) + val newElements = ElementRenderer.createElements(entry, mapping) + this.elements.addAll(newElements) val parent = mapping.blockModels[ModIdentifier(entry["model"].asString.replace("block/", ""))] textures.putAll(parent!!.textures) } - constructor(models: List, mapping: VersionMapping) : this() { + constructor(models: List, mapping: VersionMapping) { for (state in models) { loadElements(state, mapping) } @@ -49,35 +64,42 @@ class BlockRenderer() { textureMapping[key] = texture!! } } + for (direction in Directions.DIRECTIONS) { + for (element in elements) { + if (element.isCullFace(direction)) { + cullFaces.add(direction) + } + if (textureMapping[element.getTexture(direction)]?.isTransparent == true) { // THIS IS BROKEN! + transparentFaces.add(direction) + } + if (element.isFullTowards(direction)) { + fullFaceDirections.add(direction) + } + } + } } fun render(position: Vec3, data: MutableList, neighbourBlocks: Array) { - val modelMatrix = Mat4().translate(Vec3(position.x, position.y, position.z)) - .rotate(rotation.z, Vec3(0, 0, -1)) - .rotate(rotation.y, Vec3(0, -1, 0)) - .rotate(rotation.x, Vec3(1, 0, 0 )) - // ToDo: this should be made easier/more efficient + val modelMatrix = Mat4().translate(position) for (direction in Directions.DIRECTIONS) { for (element in elements) { - val blockFullFace = fullFaceDirections.contains(direction) + val cullFace = cullFaces.contains(direction) var neighbourBlockFullFace = false - neighbourBlocks[direction.ordinal]?.blockModels?.let { // ToDo: Improve this + neighbourBlocks[direction.ordinal]?.blockRenderers?.let { // ToDo: Improve this + val testDirection = direction.inverse() for (model in it) { - if (model.fullFaceDirections.contains(direction.inverse())) { + if (model.fullFaceDirections.contains(testDirection) && ! model.transparentFaces.contains(testDirection)) { neighbourBlockFullFace = true break } } } - if (blockFullFace && neighbourBlockFullFace) { + if (neighbourBlockFullFace && cullFace) { continue } - if (!blockFullFace && neighbourBlockFullFace) { - continue - } - element.render(textureMapping, modelMatrix, direction, rotation, data) + element.render(textureMapping, modelMatrix, direction, data) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt index 624511ade..57224a0f4 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt @@ -1,6 +1,20 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger, Lukas Eisenhauer + * + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + package de.bixilon.minosoft.gui.rendering.chunk.models.renderable import com.google.gson.JsonObject +import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.mappings.ModIdentifier import de.bixilon.minosoft.data.mappings.versions.VersionMapping @@ -15,17 +29,25 @@ import glm_.vec3.Vec3 import glm_.vec4.Vec4 class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvlock: Boolean) { + private val fullFaceDirections: MutableSet = mutableSetOf() private val faces: MutableMap = element.faces private var positions: Array = element.positions.clone() + private val directionMapping: MutableMap = mutableMapOf() init { - BlockModelElement.rotatePositionsAxes(positions, rotation) + rotatePositionsAxes(positions, rotation) // TODO : uvlock + for (direction in Directions.DIRECTIONS) { + if (positions.containsAllVectors(BlockModelElement.fullTestPositions[direction], 0.0001f)) { // TODO: check if texture is transparent ==> && ! texture.isTransparent + fullFaceDirections.add(direction) + } + directionMapping[direction] = getRotatedDirection(rotation, direction) + } } - fun render(textureMapping: MutableMap, modelMatrix: Mat4, direction: Directions, rotation: Vec3, data: MutableList) { - val realDirection = BlockModelElement.getRotatedDirection(rotation, direction) + fun render(textureMapping: MutableMap, modelMatrix: Mat4, direction: Directions, data: MutableList) { + val realDirection = directionMapping[direction]!! // BlockModelElement.getRotatedDirection(rotation, direction) val positionTemplate = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[realDirection.ordinal] val face = faces[realDirection] ?: return // Not our face @@ -53,19 +75,27 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvlock: Boolea } fun createQuad(drawPositions: Array, texturePositions: Array) { - addToData(drawPositions[0], texturePositions[1]!!) - addToData(drawPositions[3], texturePositions[2]!!) - addToData(drawPositions[2], texturePositions[3]!!) - addToData(drawPositions[2], texturePositions[3]!!) - addToData(drawPositions[1], texturePositions[0]!!) - addToData(drawPositions[0], texturePositions[1]!!) + for (vertex in drawOrder) { + addToData(drawPositions[vertex.first], texturePositions[vertex.second]!!) + } } - val texturePositions = face.getTexturePositionArray(realDirection) createQuad(drawPositions, texturePositions) } + fun getTexture(direction: Directions): String? { + return faces[direction]?.textureName + } + + fun isCullFace(direction: Directions): Boolean { + return faces[direction]?.cullFace == direction + } + + fun isFullTowards(direction: Directions): Boolean { + return fullFaceDirections.contains(direction) + } + companion object { fun createElements(state: JsonObject, mapping: VersionMapping): MutableList { val rotation = glm.radians(vec3InJsonObject(state)) @@ -81,5 +111,47 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvlock: Boolea private fun vec3InJsonObject(json: JsonObject): Vec3 { return Vec3(json["x"]?.asFloat?: 0, json["y"]?.asFloat?: 0, json["z"]?.asFloat?: 0) } + + val drawOrder = arrayOf( + Pair(0, 1), + Pair(3, 2), + Pair(2, 3), + Pair(2, 3), + Pair(1, 0), + Pair(0, 1), + ) + + private fun Array.containsAllVectors(set: Set?, margin: Float): Boolean { + for (position in set!!) { + var isIn = false + for (testposition in this) { + if ((position - testposition).length() < margin) { + isIn = true + } + } + if (! isIn) { + return false + } + } + return true + } + + fun getRotatedDirection(rotation: Vec3, direction: Directions): Directions { + if (rotation == Vec3(0, 0, 0)) { + return direction + } + var rotatedDirectionVector = BlockModelElement.rotateVector(direction.directionVector, rotation.z.toDouble(), Axes.Z) + rotatedDirectionVector = BlockModelElement.rotateVector(rotatedDirectionVector, rotation.y.toDouble(), Axes.Y) + return Directions.byDirection(BlockModelElement.rotateVector(rotatedDirectionVector, rotation.x.toDouble(), Axes.X)) + } + + fun rotatePositionsAxes(positions: Array, angles: Vec3) { + if (angles == Vec3()) { + return + } + BlockModelElement.rotatePositions(positions, Axes.X, angles.x.toDouble(), Vec3()) + BlockModelElement.rotatePositions(positions, Axes.Y, angles.y.toDouble(), Vec3()) + BlockModelElement.rotatePositions(positions, Axes.Z, angles.z.toDouble(), Vec3()) + } } }