mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 09:26:11 -04:00
tint optimisations, refactor and abstract color maps
This commit is contained in:
parent
272df21f9e
commit
1686a6695d
@ -11,17 +11,9 @@
|
|||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.bixilon.minosoft.data.registries.biomes
|
package de.bixilon.minosoft.data.registries.versions.registries.pixlyzer
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
import org.testng.annotations.Test
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
|
|
||||||
class BiomeTest {
|
@Test(groups = ["pixlyzer"], dependsOnGroups = ["version"], priority = Int.MAX_VALUE, timeOut = 15000L)
|
||||||
|
class `1_20_4` : PixLyzerLoadingTest("1.20.4")
|
||||||
@Test
|
|
||||||
fun `color map index`() {
|
|
||||||
val biome = Biome(minecraft("plains"), temperature = 0.8f, downfall = 0.4f)
|
|
||||||
assertEquals(biome.colorMapPixelIndex, 44338)
|
|
||||||
}
|
|
||||||
}
|
|
@ -67,6 +67,13 @@ class RGB8BufferTest {
|
|||||||
assertEquals(source.getA(3, 3), 0xFF)
|
assertEquals(source.getA(3, 3), 0xFF)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun `get rgb at 3,3`() {
|
||||||
|
val source = RGB8Buffer(Vec2i(12, 13))
|
||||||
|
source.data.put(117 + 0, 0x11).put(117 + 1, 0x22).put(117 + 2, 0x33)
|
||||||
|
val rgba = source.getRGB(3, 3)
|
||||||
|
assertEquals(rgba, 0x112233)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun `put complete texture`() {
|
fun `put complete texture`() {
|
||||||
val source = RGB8Buffer(Vec2i(12, 13))
|
val source = RGB8Buffer(Vec2i(12, 13))
|
||||||
|
@ -69,6 +69,12 @@ class RGBA8BufferTest {
|
|||||||
assertEquals(source.getB(3, 3), 0x33)
|
assertEquals(source.getB(3, 3), 0x33)
|
||||||
assertEquals(source.getA(3, 3), 0x44)
|
assertEquals(source.getA(3, 3), 0x44)
|
||||||
}
|
}
|
||||||
|
fun `get rgb at 3,3`() {
|
||||||
|
val source = RGBA8Buffer(Vec2i(12, 13))
|
||||||
|
source.data.put(156 + 0, 0x11).put(156 + 1, 0x22).put(156 + 2, 0x33).put(156 + 3, 0x44)
|
||||||
|
val rgba = source.getRGB(3, 3)
|
||||||
|
assertEquals(rgba, 0x112233)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun `put complete texture`() {
|
fun `put complete texture`() {
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.tint.tints
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
||||||
|
import org.testng.Assert.assertEquals
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
|
@Test(groups = ["biome"])
|
||||||
|
class ColorMapTintTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `plains color map index`() {
|
||||||
|
val biome = Biome(minecraft("plains"), temperature = 0.8f, downfall = 0.4f)
|
||||||
|
assertEquals(biome.temperatureIndex, 50)
|
||||||
|
assertEquals(biome.downfallIndex, 173)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `dessert color map index`() {
|
||||||
|
val biome = Biome(minecraft("dessert"), temperature = 2.0f, downfall = 0.0f)
|
||||||
|
assertEquals(biome.temperatureIndex, 0)
|
||||||
|
assertEquals(biome.downfallIndex, 255)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.tint.tints.grass
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.assets.MemoryAssetsManager
|
||||||
|
import org.testng.Assert.assertEquals
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
|
@Test(groups = ["tint"])
|
||||||
|
class GrassTintCalculatorTest {
|
||||||
|
private val map by lazy {
|
||||||
|
val map = GrassTintCalculator()
|
||||||
|
val assets = MemoryAssetsManager()
|
||||||
|
assets.push(GrassTintCalculator.FILE, GrassTintCalculatorTest::class.java.getResourceAsStream("/tint/grass.png")!!.readAllBytes())
|
||||||
|
map.init(assets)
|
||||||
|
|
||||||
|
return@lazy map
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun `color of dessert`() {
|
||||||
|
assertEquals(map.getColor(255, 0), 0xBFB755)
|
||||||
|
}
|
||||||
|
}
|
BIN
src/integration-test/resources/tint/foliage.png
Normal file
BIN
src/integration-test/resources/tint/foliage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
src/integration-test/resources/tint/grass.png
Normal file
BIN
src/integration-test/resources/tint/grass.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
@ -25,7 +25,7 @@ import de.bixilon.minosoft.assets.properties.manager.pack.PackProperties
|
|||||||
import de.bixilon.minosoft.assets.util.FileAssetsTypes
|
import de.bixilon.minosoft.assets.util.FileAssetsTypes
|
||||||
import de.bixilon.minosoft.assets.util.FileAssetsUtil
|
import de.bixilon.minosoft.assets.util.FileAssetsUtil
|
||||||
import de.bixilon.minosoft.assets.util.HashTypes
|
import de.bixilon.minosoft.assets.util.HashTypes
|
||||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readArchive
|
import de.bixilon.minosoft.assets.util.InputStreamUtil.readTarArchive
|
||||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readZipArchive
|
import de.bixilon.minosoft.assets.util.InputStreamUtil.readZipArchive
|
||||||
import de.bixilon.minosoft.assets.util.PathUtil
|
import de.bixilon.minosoft.assets.util.PathUtil
|
||||||
import de.bixilon.minosoft.config.profile.profiles.resources.ResourcesProfile
|
import de.bixilon.minosoft.config.profile.profiles.resources.ResourcesProfile
|
||||||
@ -66,7 +66,7 @@ class JarAssetsManager(
|
|||||||
|
|
||||||
|
|
||||||
private fun tryLoadAssets(): Boolean {
|
private fun tryLoadAssets(): Boolean {
|
||||||
val assets = FileAssetsUtil.readOrNull(jarAssetsHash, FileAssetsTypes.GAME, verify = profile.verify)?.let { ByteArrayInputStream(it).readArchive() } ?: return false
|
val assets = FileAssetsUtil.readOrNull(jarAssetsHash, FileAssetsTypes.GAME, verify = profile.verify)?.let { ByteArrayInputStream(it).readTarArchive() } ?: return false
|
||||||
|
|
||||||
for ((path, data) in assets) {
|
for ((path, data) in assets) {
|
||||||
this.assets[path.removePrefix("assets/" + Namespaces.MINECRAFT + "/")] = data
|
this.assets[path.removePrefix("assets/" + Namespaces.MINECRAFT + "/")] = data
|
||||||
|
@ -21,9 +21,7 @@ import de.bixilon.kutil.cast.CastUtil.unsafeCast
|
|||||||
import de.bixilon.kutil.json.JsonObject
|
import de.bixilon.kutil.json.JsonObject
|
||||||
import de.bixilon.mbf.MBFBinaryReader
|
import de.bixilon.mbf.MBFBinaryReader
|
||||||
import de.bixilon.minosoft.util.json.Jackson
|
import de.bixilon.minosoft.util.json.Jackson
|
||||||
import de.matthiasmann.twl.utils.PNGDecoder
|
|
||||||
import org.kamranzafar.jtar.TarInputStream
|
import org.kamranzafar.jtar.TarInputStream
|
||||||
import org.lwjgl.BufferUtils
|
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
|
|
||||||
@ -50,13 +48,7 @@ object InputStreamUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun InputStream.readJsonObject(close: Boolean = true): JsonObject {
|
fun InputStream.readJsonObject(close: Boolean = true): JsonObject {
|
||||||
try {
|
return readJson(close = close, reader = Jackson.MAP_READER)
|
||||||
return Jackson.MAPPER.readValue(this, Jackson.JSON_MAP_TYPE)
|
|
||||||
} finally {
|
|
||||||
if (close) {
|
|
||||||
this.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> InputStream.readJson(close: Boolean = true): T {
|
inline fun <reified T> InputStream.readJson(close: Boolean = true): T {
|
||||||
@ -89,7 +81,7 @@ object InputStreamUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun InputStream.readArchive(): Map<String, ByteArray> {
|
fun InputStream.readTarArchive(): Map<String, ByteArray> {
|
||||||
val content: MutableMap<String, ByteArray> = mutableMapOf()
|
val content: MutableMap<String, ByteArray> = mutableMapOf()
|
||||||
val stream = TarInputStream(this)
|
val stream = TarInputStream(this)
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -111,21 +103,6 @@ object InputStreamUtil {
|
|||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|
||||||
fun InputStream.readRGBArray(): IntArray {
|
|
||||||
val decoder = PNGDecoder(this)
|
|
||||||
|
|
||||||
val buffer = BufferUtils.createByteBuffer(decoder.width * decoder.height * PNGDecoder.Format.RGB.numComponents)
|
|
||||||
decoder.decode(buffer, decoder.width * PNGDecoder.Format.RGB.numComponents, PNGDecoder.Format.RGB)
|
|
||||||
buffer.flip()
|
|
||||||
val colors = IntArray(decoder.width * decoder.height)
|
|
||||||
|
|
||||||
for (i in colors.indices) {
|
|
||||||
colors[i] = ((buffer.get().toInt() and 0xFF) shl 16) or ((buffer.get().toInt() and 0xFF) shl 8) or (buffer.get().toInt() and 0xFF)
|
|
||||||
}
|
|
||||||
|
|
||||||
return colors
|
|
||||||
}
|
|
||||||
|
|
||||||
fun InputStream.readMBFMap(): Map<Any, Any> {
|
fun InputStream.readMBFMap(): Map<Any, Any> {
|
||||||
return MBFBinaryReader(this).readMBF().data.unsafeCast()
|
return MBFBinaryReader(this).readMBF().data.unsafeCast()
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
package de.bixilon.minosoft.data.registries.biomes
|
package de.bixilon.minosoft.data.registries.biomes
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.func.common.clamp
|
|
||||||
import de.bixilon.kutil.json.JsonUtil.toJsonObject
|
import de.bixilon.kutil.json.JsonUtil.toJsonObject
|
||||||
import de.bixilon.kutil.primitive.FloatUtil.toFloat
|
import de.bixilon.kutil.primitive.FloatUtil.toFloat
|
||||||
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
@ -20,9 +19,8 @@ import de.bixilon.minosoft.data.registries.registries.Registries
|
|||||||
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
||||||
import de.bixilon.minosoft.data.registries.registries.registry.codec.IdentifierCodec
|
import de.bixilon.minosoft.data.registries.registries.registry.codec.IdentifierCodec
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
|
||||||
import de.bixilon.minosoft.gui.rendering.tint.TintManager.Companion.jsonTint
|
import de.bixilon.minosoft.gui.rendering.tint.TintManager.Companion.jsonTint
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.gui.rendering.tint.tints.ColorMapTint
|
||||||
|
|
||||||
data class Biome(
|
data class Biome(
|
||||||
override val identifier: ResourceLocation,
|
override val identifier: ResourceLocation,
|
||||||
@ -34,26 +32,15 @@ data class Biome(
|
|||||||
val waterFogColor: RGBColor? = null,
|
val waterFogColor: RGBColor? = null,
|
||||||
val precipitation: BiomePrecipitation? = null,
|
val precipitation: BiomePrecipitation? = null,
|
||||||
) : RegistryItem() {
|
) : RegistryItem() {
|
||||||
val grassColorModifier = GrassColorModifiers.BIOME_MAP[identifier]
|
val grassModifier = GrassColorModifiers.BIOME_MAP[identifier]
|
||||||
val temperatureColorMapCoordinate = getColorMapCoordinate(temperature)
|
|
||||||
val downfallColorMapCoordinate = getColorMapCoordinate(downfall * temperature)
|
|
||||||
val colorMapPixelIndex = downfallColorMapCoordinate shl 8 or temperatureColorMapCoordinate
|
|
||||||
|
|
||||||
|
|
||||||
fun getClampedTemperature(height: Int): Int {
|
val temperatureIndex = ColorMapTint.getIndex(temperature)
|
||||||
return getColorMapCoordinate((temperature + ((height - ProtocolDefinition.SEA_LEVEL_HEIGHT).clamp(1, Int.MAX_VALUE) * ProtocolDefinition.HEIGHT_SEA_LEVEL_MODIFIER)).clamp(0.0f, 1.0f))
|
val downfallIndex = ColorMapTint.getIndex(downfall * temperature)
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return identifier.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : IdentifierCodec<Biome> {
|
companion object : IdentifierCodec<Biome> {
|
||||||
|
|
||||||
private fun getColorMapCoordinate(value: Float): Int {
|
|
||||||
return ((1.0 - value.clamp(0.0f, 1.0f)) * RenderConstants.COLORMAP_SIZE).toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserialize(registries: Registries?, identifier: ResourceLocation, data: Map<String, Any>): Biome {
|
override fun deserialize(registries: Registries?, identifier: ResourceLocation, data: Map<String, Any>): Biome {
|
||||||
val effects = data["effects"].toJsonObject() // nbt data
|
val effects = data["effects"].toJsonObject() // nbt data
|
||||||
val skyColor = (data["sky_color"] ?: effects?.get("sky_color"))?.jsonTint()
|
val skyColor = (data["sky_color"] ?: effects?.get("sky_color"))?.jsonTint()
|
||||||
|
@ -18,9 +18,6 @@ import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
|||||||
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
||||||
|
|
||||||
object RenderConstants {
|
object RenderConstants {
|
||||||
const val COLORMAP_SIZE = 255
|
|
||||||
|
|
||||||
|
|
||||||
val TEXT_BACKGROUND_COLOR = RGBColor(0, 0, 0, 80)
|
val TEXT_BACKGROUND_COLOR = RGBColor(0, 0, 0, 80)
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class ChunkMeshingQueue(
|
|||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var working = false
|
private var working = false
|
||||||
private val queue: MutableList<WorldQueueItem> = mutableListOf()
|
private val queue: MutableList<WorldQueueItem> = ArrayList()
|
||||||
private val set: MutableSet<WorldQueueItem> = HashSet()
|
private val set: MutableSet<WorldQueueItem> = HashSet()
|
||||||
|
|
||||||
private val lock = SimpleLock()
|
private val lock = SimpleLock()
|
||||||
|
@ -21,7 +21,7 @@ import de.bixilon.kutil.concurrent.pool.runnable.ForcePooledRunnable
|
|||||||
import de.bixilon.kutil.concurrent.pool.runnable.SimplePoolRunnable
|
import de.bixilon.kutil.concurrent.pool.runnable.SimplePoolRunnable
|
||||||
import de.bixilon.kutil.latch.AbstractLatch
|
import de.bixilon.kutil.latch.AbstractLatch
|
||||||
import de.bixilon.kutil.latch.AbstractLatch.Companion.child
|
import de.bixilon.kutil.latch.AbstractLatch.Companion.child
|
||||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readAsString
|
import de.bixilon.minosoft.assets.util.InputStreamUtil.readJson
|
||||||
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureStates
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureStates
|
||||||
@ -31,7 +31,6 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture
|
|||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.file.PNGTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.file.PNGTexture
|
||||||
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
||||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
import de.bixilon.minosoft.util.json.Jackson
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
abstract class StaticTextureArray(
|
abstract class StaticTextureArray(
|
||||||
@ -88,8 +87,8 @@ abstract class StaticTextureArray(
|
|||||||
|
|
||||||
private fun readImageProperties(texture: ResourceLocation): ImageProperties? {
|
private fun readImageProperties(texture: ResourceLocation): ImageProperties? {
|
||||||
try {
|
try {
|
||||||
val data = context.connection.assetsManager.getOrNull("$texture.mcmeta".toResourceLocation())?.readAsString() ?: return null
|
val stream = context.connection.assetsManager.getOrNull("$texture.mcmeta".toResourceLocation()) ?: return null
|
||||||
return Jackson.MAPPER.readValue(data, ImageProperties::class.java)
|
return stream.readJson(reader = ImageProperties.READER)
|
||||||
} catch (error: Throwable) {
|
} catch (error: Throwable) {
|
||||||
error.printStackTrace()
|
error.printStackTrace()
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,11 @@ class RGB8Buffer(
|
|||||||
return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or 0xFF
|
return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getRGB(x: Int, y: Int): Int {
|
||||||
|
val stride = stride(x, y)
|
||||||
|
return (this[stride + 0] shl 16) or (this[stride + 1] shl 8) or this[stride + 2]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun getR(x: Int, y: Int) = this[stride(x, y) + 0]
|
override fun getR(x: Int, y: Int) = this[stride(x, y) + 0]
|
||||||
override fun getG(x: Int, y: Int) = this[stride(x, y) + 1]
|
override fun getG(x: Int, y: Int) = this[stride(x, y) + 1]
|
||||||
@ -70,6 +75,7 @@ class RGB8Buffer(
|
|||||||
|
|
||||||
|
|
||||||
private fun stride(x: Int, y: Int): Int {
|
private fun stride(x: Int, y: Int): Int {
|
||||||
|
if (x >= size.x || y >= size.y) throw IllegalArgumentException("Can not access pixel at ($x,$y), exceeds size: $size")
|
||||||
return ((size.x * y) + x) * bytes
|
return ((size.x * y) + x) * bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,18 +58,21 @@ class RGBA8Buffer(
|
|||||||
|
|
||||||
override fun getRGBA(x: Int, y: Int): Int {
|
override fun getRGBA(x: Int, y: Int): Int {
|
||||||
val stride = stride(x, y)
|
val stride = stride(x, y)
|
||||||
if (stride > data.capacity()) {
|
|
||||||
throw IllegalArgumentException("Can not access pixel at ($x,$y), exceeds size: $size")
|
|
||||||
}
|
|
||||||
return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or (this[stride + 3] shl 0)
|
return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or (this[stride + 3] shl 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getRGB(x: Int, y: Int): Int {
|
||||||
|
val stride = stride(x, y)
|
||||||
|
return (this[stride + 0] shl 16) or (this[stride + 1] shl 8) or this[stride + 2]
|
||||||
|
}
|
||||||
|
|
||||||
override fun getR(x: Int, y: Int) = this[stride(x, y) + 0]
|
override fun getR(x: Int, y: Int) = this[stride(x, y) + 0]
|
||||||
override fun getG(x: Int, y: Int) = this[stride(x, y) + 1]
|
override fun getG(x: Int, y: Int) = this[stride(x, y) + 1]
|
||||||
override fun getB(x: Int, y: Int) = this[stride(x, y) + 2]
|
override fun getB(x: Int, y: Int) = this[stride(x, y) + 2]
|
||||||
override fun getA(x: Int, y: Int) = this[stride(x, y) + 3]
|
override fun getA(x: Int, y: Int) = this[stride(x, y) + 3]
|
||||||
|
|
||||||
private fun stride(x: Int, y: Int): Int {
|
private fun stride(x: Int, y: Int): Int {
|
||||||
|
if (x >= size.x || y >= size.y) throw IllegalArgumentException("Can not access pixel at ($x,$y), exceeds size: $size")
|
||||||
return ((size.x * y) + x) * bytes
|
return ((size.x * y) + x) * bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,8 @@ interface TextureBuffer {
|
|||||||
fun getB(x: Int, y: Int): Int
|
fun getB(x: Int, y: Int): Int
|
||||||
fun getA(x: Int, y: Int): Int
|
fun getA(x: Int, y: Int): Int
|
||||||
|
|
||||||
|
fun getRGB(x: Int, y: Int): Int
|
||||||
|
|
||||||
fun getRGBA(x: Int, y: Int): Int
|
fun getRGBA(x: Int, y: Int): Int
|
||||||
fun setRGBA(x: Int, y: Int, value: Int)
|
fun setRGBA(x: Int, y: Int, value: Int)
|
||||||
fun setRGBA(x: Int, y: Int, red: Int, green: Int, blue: Int, alpha: Int)
|
fun setRGBA(x: Int, y: Int, red: Int, green: Int, blue: Int, alpha: Int)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2021 Moritz Zwerger
|
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* 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 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.
|
||||||
*
|
*
|
||||||
@ -14,6 +14,7 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.textures.properties
|
package de.bixilon.minosoft.gui.rendering.textures.properties
|
||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture
|
||||||
|
import de.bixilon.minosoft.util.json.Jackson
|
||||||
|
|
||||||
data class ImageProperties(
|
data class ImageProperties(
|
||||||
val texture: TextureProperties = TextureProperties(),
|
val texture: TextureProperties = TextureProperties(),
|
||||||
@ -27,5 +28,6 @@ data class ImageProperties(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT = ImageProperties()
|
val DEFAULT = ImageProperties()
|
||||||
|
val READER = Jackson.MAPPER.readerFor(ImageProperties::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.tint.tints
|
||||||
|
|
||||||
|
import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll
|
||||||
|
import de.bixilon.minosoft.assets.AssetsManager
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.data.buffer.TextureBuffer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.readTexture
|
||||||
|
import de.bixilon.minosoft.gui.rendering.tint.TintProvider
|
||||||
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
|
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||||
|
|
||||||
|
abstract class ColorMapTint(
|
||||||
|
private val file: ResourceLocation,
|
||||||
|
) : TintProvider {
|
||||||
|
protected var map: IntArray? = null
|
||||||
|
|
||||||
|
fun init(assets: AssetsManager) {
|
||||||
|
val map = ignoreAll { assets[file].readTexture() } ?: return
|
||||||
|
if (map.size.x != SIZE || map.size.y != SIZE) {
|
||||||
|
Log.log(LogMessageType.LOADING, LogLevels.WARN) { "Color map ($file) has invalid size: ${map.size}" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.map = map.toColorMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TextureBuffer.toColorMap(): IntArray {
|
||||||
|
val array = IntArray(size.x * size.y)
|
||||||
|
var index = 0
|
||||||
|
for (y in 0 until size.y) {
|
||||||
|
for (x in 0 until size.x) {
|
||||||
|
array[index++] = getRGB(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val SIZE = 256
|
||||||
|
|
||||||
|
fun getIndex(value: Float): Int {
|
||||||
|
if (value <= 0.0f) return SIZE - 1
|
||||||
|
if (value >= 1.0f) return 0
|
||||||
|
|
||||||
|
val delta = 1.0f - value
|
||||||
|
return (delta * (SIZE - 1)).toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,48 +13,33 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.tint.tints.grass
|
package de.bixilon.minosoft.gui.rendering.tint.tints.grass
|
||||||
|
|
||||||
import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll
|
import de.bixilon.minosoft.data.container.stack.ItemStack
|
||||||
import de.bixilon.minosoft.assets.AssetsManager
|
|
||||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray
|
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
import de.bixilon.minosoft.data.registries.biomes.GrassColorModifiers
|
import de.bixilon.minosoft.data.registries.biomes.GrassColorModifiers
|
||||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||||
import de.bixilon.minosoft.data.registries.blocks.types.building.dirt.GrassBlock
|
import de.bixilon.minosoft.data.registries.blocks.types.building.dirt.GrassBlock
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.Colors
|
import de.bixilon.minosoft.data.text.formatting.color.Colors
|
||||||
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
||||||
import de.bixilon.minosoft.gui.rendering.tint.TintProvider
|
import de.bixilon.minosoft.gui.rendering.tint.tints.ColorMapTint
|
||||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
|
||||||
|
|
||||||
class GrassTintCalculator : TintProvider {
|
class GrassTintCalculator : ColorMapTint(FILE) {
|
||||||
private lateinit var colorMap: IntArray
|
|
||||||
|
|
||||||
fun init(assetsManager: AssetsManager) {
|
fun getColor(downfallIndex: Int, temperatureIndex: Int): Int {
|
||||||
colorMap = ignoreAll { assetsManager["minecraft:colormap/grass".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256)
|
val map = map ?: return FALLBACK
|
||||||
}
|
|
||||||
|
|
||||||
inline fun getColor(downfall: Int, temperature: Int): Int {
|
val color = map[downfallIndex shl 8 or temperatureIndex]
|
||||||
return getColor(downfall shl 8 or temperature)
|
if (color == 0xFFFFFF) return 0x48B518
|
||||||
}
|
|
||||||
|
|
||||||
fun getColor(colorMapPixelIndex: Int): Int {
|
|
||||||
if (colorMapPixelIndex > colorMap.size) {
|
|
||||||
return 0xFF00FF // ToDo: Is this correct? Was used in my old implementation
|
|
||||||
}
|
|
||||||
val color = colorMap[colorMapPixelIndex]
|
|
||||||
if (color == 0xFFFFFF) {
|
|
||||||
return 0x48B518
|
|
||||||
}
|
|
||||||
|
|
||||||
return color
|
return color
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBlockColor(biome: Biome?): Int {
|
fun getBlockColor(biome: Biome?): Int {
|
||||||
if (biome == null) {
|
if (biome == null) return getColor(127, 255)
|
||||||
return getColor(127, 255)
|
|
||||||
}
|
|
||||||
val color = getColor(biome.colorMapPixelIndex)
|
|
||||||
|
|
||||||
return when (biome.grassColorModifier) {
|
val color = getColor(biome.downfallIndex, biome.temperatureIndex)
|
||||||
|
|
||||||
|
return when (biome.grassModifier) {
|
||||||
null -> color
|
null -> color
|
||||||
GrassColorModifiers.SWAMP -> 0x6A7039 // ToDo: Biome noise is applied here
|
GrassColorModifiers.SWAMP -> 0x6A7039 // ToDo: Biome noise is applied here
|
||||||
GrassColorModifiers.DARK_FOREST -> (color and 0xFEFEFE) + 0x28340A shr 1
|
GrassColorModifiers.DARK_FOREST -> (color and 0xFEFEFE) + 0x28340A shr 1
|
||||||
@ -71,4 +56,13 @@ class GrassTintCalculator : TintProvider {
|
|||||||
}
|
}
|
||||||
return getBlockColor(biome)
|
return getBlockColor(biome)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getItemColor(stack: ItemStack, tintIndex: Int): Int {
|
||||||
|
return getColor(127, 255) // TODO: verify
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val FILE = minecraft("colormap/grass").texture()
|
||||||
|
private const val FALLBACK = 0xFF00FF // ToDo: Is this correct? Was used in my old implementation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,29 +13,23 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.tint.tints.plants
|
package de.bixilon.minosoft.gui.rendering.tint.tints.plants
|
||||||
|
|
||||||
import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll
|
import de.bixilon.kotlinglm.func.common.clamp
|
||||||
import de.bixilon.minosoft.assets.AssetsManager
|
|
||||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray
|
|
||||||
import de.bixilon.minosoft.data.container.stack.ItemStack
|
import de.bixilon.minosoft.data.container.stack.ItemStack
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
||||||
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
||||||
import de.bixilon.minosoft.gui.rendering.tint.TintProvider
|
import de.bixilon.minosoft.gui.rendering.tint.tints.ColorMapTint
|
||||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
|
||||||
|
|
||||||
class FoliageTintCalculator : TintProvider {
|
class FoliageTintCalculator : ColorMapTint(FILE) {
|
||||||
private lateinit var colorMap: IntArray
|
|
||||||
|
|
||||||
fun init(assetsManager: AssetsManager) {
|
|
||||||
colorMap = ignoreAll { assetsManager["minecraft:colormap/foliage".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBlockColor(biome: Biome?, y: Int): Int {
|
fun getBlockColor(biome: Biome?, y: Int): Int {
|
||||||
if (biome == null) {
|
if (biome == null) return FALLBACK_COLOR
|
||||||
return FALLBACK_COLOR
|
val map = this.map ?: return FALLBACK_COLOR
|
||||||
}
|
|
||||||
// ToDo: Override
|
// ToDo: Override
|
||||||
return colorMap[biome.downfallColorMapCoordinate shl 8 or biome.getClampedTemperature(y)]
|
val temperature = modifyTemperature(biome.temperature, y)
|
||||||
|
return map[biome.downfallIndex shl 8 or temperature]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBlockColor(blockState: BlockState, biome: Biome?, x: Int, y: Int, z: Int, tintIndex: Int): Int {
|
override fun getBlockColor(blockState: BlockState, biome: Biome?, x: Int, y: Int, z: Int, tintIndex: Int): Int {
|
||||||
@ -51,6 +45,19 @@ class FoliageTintCalculator : TintProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val FILE = minecraft("colormap/foliage").texture()
|
||||||
private const val FALLBACK_COLOR = 0x48B518
|
private const val FALLBACK_COLOR = 0x48B518
|
||||||
|
|
||||||
|
// not sure if that is accurate or relevant
|
||||||
|
private const val SEA_LEVEL = 62
|
||||||
|
private const val SEA_LEVEL_MODIFIER = 0.00166667f
|
||||||
|
|
||||||
|
|
||||||
|
fun modifyTemperature(temperature: Float, height: Int): Int {
|
||||||
|
val modifier = maxOf(1, height - SEA_LEVEL) * SEA_LEVEL_MODIFIER
|
||||||
|
val modified = (temperature + modifier).clamp(0.0f, 1.0f)
|
||||||
|
|
||||||
|
return getIndex(modified)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,6 @@ public final class ProtocolDefinition {
|
|||||||
|
|
||||||
public static final float VELOCITY_NETWORK_DIVIDER = 8000.0f;
|
public static final float VELOCITY_NETWORK_DIVIDER = 8000.0f;
|
||||||
|
|
||||||
public static final int SEA_LEVEL_HEIGHT = 62;
|
|
||||||
|
|
||||||
public static final float HEIGHT_SEA_LEVEL_MODIFIER = 0.00166667f;
|
|
||||||
|
|
||||||
public static final RGBColor DEFAULT_COLOR = ChatColors.WHITE;
|
public static final RGBColor DEFAULT_COLOR = ChatColors.WHITE;
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ object Jackson {
|
|||||||
|
|
||||||
|
|
||||||
val JSON_MAP_TYPE: MapType = MAPPER.typeFactory.constructMapType(HashMap::class.java, Any::class.java, Any::class.java)
|
val JSON_MAP_TYPE: MapType = MAPPER.typeFactory.constructMapType(HashMap::class.java, Any::class.java, Any::class.java)
|
||||||
|
val MAP_READER = MAPPER.readerFor(JSON_MAP_TYPE)
|
||||||
|
|
||||||
fun init() = Unit
|
fun init() = Unit
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user