mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 02:45:13 -04:00
wighted block state model/apply
This commit is contained in:
parent
955bf59ace
commit
0a435274b5
@ -76,7 +76,6 @@ class BlockStateApplyTest {
|
||||
x = 0,
|
||||
y = 0,
|
||||
uvLock = false,
|
||||
weight = 1,
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ import de.bixilon.kotlinglm.vec3.Vec3i
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||
import de.bixilon.minosoft.gui.rendering.world.entities.BlockEntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.world.entities.MeshedBlockEntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.world.entities.MeshedEntityRenderer
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
abstract class MeshedBlockEntity(connection: PlayConnection) : BlockEntity(connection) {
|
||||
|
||||
override fun getRenderer(context: RenderContext, blockState: BlockState, blockPosition: Vec3i, light: Int): MeshedBlockEntityRenderer<*>? {
|
||||
override fun getRenderer(context: RenderContext, blockState: BlockState, blockPosition: Vec3i, light: Int): MeshedEntityRenderer<*> {
|
||||
var renderer = this.renderer
|
||||
if (renderer is MeshedBlockEntityRenderer<*> && renderer.blockState == blockState) {
|
||||
if (renderer is MeshedEntityRenderer && renderer.blockState == blockState) {
|
||||
return renderer
|
||||
}
|
||||
renderer = createMeshedRenderer(context, blockState, blockPosition)
|
||||
@ -36,5 +36,5 @@ abstract class MeshedBlockEntity(connection: PlayConnection) : BlockEntity(conne
|
||||
throw IllegalAccessException()
|
||||
}
|
||||
|
||||
abstract fun createMeshedRenderer(context: RenderContext, blockState: BlockState, blockPosition: Vec3i): MeshedBlockEntityRenderer<*>
|
||||
abstract fun createMeshedRenderer(context: RenderContext, blockState: BlockState, blockPosition: Vec3i): MeshedEntityRenderer<*>
|
||||
}
|
||||
|
@ -15,17 +15,17 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.apply
|
||||
|
||||
import de.bixilon.kutil.cast.CastUtil.unsafeCast
|
||||
import de.bixilon.kutil.json.JsonUtil.asJsonObject
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedModel
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager
|
||||
|
||||
interface BlockStateApply {
|
||||
|
||||
fun bake(textures: TextureManager): BakedModel?
|
||||
fun bake(textures: TextureManager): BlockRender?
|
||||
|
||||
companion object {
|
||||
|
||||
fun deserialize(loader: BlockLoader, data: Any): BlockStateApply {
|
||||
fun deserialize(loader: BlockLoader, data: Any): BlockStateApply? {
|
||||
if (data is Map<*, *>) return SingleBlockStateApply.deserialize(loader, data.asJsonObject())
|
||||
if (data is List<*>) return WeightedBlockStateApply.deserialize(loader, data.unsafeCast())
|
||||
|
||||
|
@ -34,7 +34,6 @@ import java.util.*
|
||||
data class SingleBlockStateApply(
|
||||
val model: BlockModel,
|
||||
val uvLock: Boolean = false,
|
||||
val weight: Int = 1,
|
||||
val x: Int = 0,
|
||||
val y: Int = 0,
|
||||
) : BlockStateApply {
|
||||
@ -84,11 +83,10 @@ data class SingleBlockStateApply(
|
||||
|
||||
fun deserialize(model: BlockModel, data: JsonObject): SingleBlockStateApply {
|
||||
val uvLock = data["uvlock"]?.toBoolean() ?: false
|
||||
val weight = data["weight"]?.toInt() ?: 1
|
||||
val x = data["x"]?.toInt()?.rotation() ?: 0
|
||||
val y = data["y"]?.toInt()?.rotation() ?: 0
|
||||
|
||||
return SingleBlockStateApply(model, uvLock, weight, x, y)
|
||||
return SingleBlockStateApply(model, uvLock, x, y)
|
||||
}
|
||||
|
||||
fun deserialize(loader: BlockLoader, data: JsonObject): SingleBlockStateApply {
|
||||
|
@ -13,26 +13,48 @@
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.models.block.state.apply
|
||||
|
||||
import de.bixilon.kutil.array.ArrayUtil.cast
|
||||
import de.bixilon.kutil.json.JsonObject
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedModel
|
||||
import de.bixilon.kutil.primitive.IntUtil.toInt
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.render.WeightedBlockRender
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager
|
||||
|
||||
data class WeightedBlockStateApply(
|
||||
val models: List<SingleBlockStateApply>
|
||||
val models: List<WeightedApply>
|
||||
) : BlockStateApply {
|
||||
|
||||
override fun bake(textures: TextureManager): BakedModel {
|
||||
TODO("Not yet implemented")
|
||||
override fun bake(textures: TextureManager): WeightedBlockRender? {
|
||||
val baked: Array<WeightedBlockRender.WeightedEntry?> = arrayOfNulls(models.size)
|
||||
var totalWeight = 0
|
||||
|
||||
for ((index, entry) in models.withIndex()) {
|
||||
val model = entry.apply.bake(textures) ?: continue
|
||||
baked[index] = WeightedBlockRender.WeightedEntry(entry.weight, model)
|
||||
totalWeight += entry.weight
|
||||
}
|
||||
|
||||
if (totalWeight == 0) return null
|
||||
|
||||
return WeightedBlockRender(baked.cast(), totalWeight)
|
||||
}
|
||||
|
||||
data class WeightedApply(
|
||||
val weight: Int,
|
||||
val apply: SingleBlockStateApply,
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
fun deserialize(loader: BlockLoader, data: List<JsonObject>): WeightedBlockStateApply {
|
||||
val models: MutableList<SingleBlockStateApply> = mutableListOf()
|
||||
fun deserialize(loader: BlockLoader, data: List<JsonObject>): WeightedBlockStateApply? {
|
||||
if (data.isEmpty()) return null
|
||||
val models: MutableList<WeightedApply> = mutableListOf()
|
||||
|
||||
for (entry in data) {
|
||||
models += SingleBlockStateApply.deserialize(loader, entry)
|
||||
var weight = entry["weight"]?.toInt() ?: 1
|
||||
if (weight < 0) weight = 1
|
||||
val apply = SingleBlockStateApply.deserialize(loader, entry)
|
||||
models += WeightedApply(weight, apply)
|
||||
}
|
||||
|
||||
return WeightedBlockStateApply(models)
|
||||
|
@ -28,9 +28,9 @@ class BakedModel(
|
||||
val particle: AbstractTexture?,
|
||||
) : BlockRender {
|
||||
|
||||
override fun getParticleTexture(random: Random, position: Vec3i) = particle
|
||||
override fun getParticleTexture(random: Random?, position: Vec3i) = particle
|
||||
|
||||
override fun render(position: BlockPosition, mesh: WorldMesh, random: Random, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
override fun render(position: BlockPosition, mesh: WorldMesh, random: Random?, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
val float = position.toVec3
|
||||
|
||||
val array = float.array
|
||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
||||
import java.util.*
|
||||
|
||||
interface BlockRender {
|
||||
fun getParticleTexture(random: Random, position: Vec3i): AbstractTexture? = null
|
||||
fun getParticleTexture(random: Random?, position: Vec3i): AbstractTexture? = null
|
||||
|
||||
fun render(position: BlockPosition, mesh: WorldMesh, random: Random, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean
|
||||
fun render(position: BlockPosition, mesh: WorldMesh, random: Random?, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean
|
||||
}
|
||||
|
@ -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.models.block.state.render
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
||||
import de.bixilon.kutil.exception.Broken
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedModel
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
class WeightedBlockRender(
|
||||
val models: Array<WeightedEntry>,
|
||||
val totalWeight: Int,
|
||||
) : BlockRender {
|
||||
|
||||
|
||||
private fun getModel(random: Random?): BlockRender {
|
||||
if (random == null) return models.first().model
|
||||
|
||||
var weightLeft = abs(random.nextLong() % totalWeight)
|
||||
|
||||
for ((weight, model) in models) {
|
||||
weightLeft -= weight
|
||||
if (weightLeft >= 0) continue
|
||||
|
||||
return model
|
||||
}
|
||||
|
||||
Broken("Could not find a model: This should never happen!")
|
||||
}
|
||||
|
||||
override fun getParticleTexture(random: Random?, position: Vec3i): AbstractTexture? {
|
||||
random?.setSeed(position.positionHash)
|
||||
return getModel(random).getParticleTexture(random, position)
|
||||
}
|
||||
|
||||
override fun render(position: BlockPosition, mesh: WorldMesh, random: Random?, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
return getModel(random).render(position, mesh, random, state, neighbours, light, tints)
|
||||
}
|
||||
|
||||
|
||||
data class WeightedEntry(
|
||||
val weight: Int,
|
||||
val model: BakedModel,
|
||||
)
|
||||
}
|
@ -43,7 +43,7 @@ interface VariantBlockModel : DirectBlockModel {
|
||||
|
||||
|
||||
for ((variant, entry) in data) {
|
||||
val apply = BlockStateApply.deserialize(loader, entry.asJsonObject())
|
||||
val apply = BlockStateApply.deserialize(loader, entry.asJsonObject()) ?: continue
|
||||
if (variant == "") {
|
||||
// no further conditions
|
||||
return SingleVariantBlockModel(apply)
|
||||
@ -51,6 +51,8 @@ interface VariantBlockModel : DirectBlockModel {
|
||||
variants[parseVariant(variant)] = apply
|
||||
}
|
||||
|
||||
if (variants.isEmpty()) return null
|
||||
|
||||
return PropertyVariantBlockModel(variants)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.world.entities
|
||||
|
||||
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
|
||||
|
||||
interface MeshedEntityRenderer<E : BlockEntity> : BlockEntityRenderer<E>, BlockRender
|
@ -32,10 +32,9 @@ import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||
import de.bixilon.minosoft.gui.rendering.font.renderer.ChatComponentRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.element.ModelElement.Companion.BLOCK_SIZE
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign
|
||||
import de.bixilon.minosoft.gui.rendering.world.entities.BlockEntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.world.entities.MeshedEntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh
|
||||
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
||||
import de.bixilon.minosoft.gui.rendering.world.preparer.cull.SolidCullSectionPreparer.Companion.SELF_LIGHT_INDEX
|
||||
@ -45,7 +44,7 @@ class SignBlockEntityRenderer(
|
||||
val sign: SignBlockEntity,
|
||||
val context: RenderContext,
|
||||
override val blockState: BlockState,
|
||||
) : BlockEntityRenderer<SignBlockEntity>, BlockRender {
|
||||
) : MeshedEntityRenderer<SignBlockEntity> {
|
||||
override val enabled: Boolean get() = false
|
||||
|
||||
private fun getRotation(): Float {
|
||||
@ -54,7 +53,7 @@ class SignBlockEntityRenderer(
|
||||
return rotation * 22.5f
|
||||
}
|
||||
|
||||
override fun render(position: Vec3i, mesh: WorldMesh, random: Random, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
override fun render(position: Vec3i, mesh: WorldMesh, random: Random?, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
val block = this.blockState.block
|
||||
if (block is StandingSignBlock) {
|
||||
renderStandingText(position, mesh, light[SELF_LIGHT_INDEX].toInt())
|
||||
|
@ -56,10 +56,9 @@ class SolidCullSectionPreparer(
|
||||
}
|
||||
|
||||
override fun prepareSolid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbourChunks: Array<Chunk>, neighbours: Array<ChunkSection?>, mesh: WorldMesh) {
|
||||
val random = Random(0L)
|
||||
val random = if (profile.antiMoirePattern) Random(0L) else null
|
||||
|
||||
|
||||
val randomness = profile.antiMoirePattern
|
||||
val isLowestSection = sectionHeight == chunk.minSection
|
||||
val isHighestSection = sectionHeight == chunk.maxSection
|
||||
val blocks = section.blocks
|
||||
@ -132,11 +131,8 @@ class SolidCullSectionPreparer(
|
||||
light[O_UP] = (light[O_UP].toInt() or 0xF0).toByte()
|
||||
}
|
||||
|
||||
if (randomness) {
|
||||
random.setSeed(position.positionHash)
|
||||
} else {
|
||||
random.setSeed(0L)
|
||||
}
|
||||
random?.setSeed(position.positionHash)
|
||||
|
||||
val tints = tintColorCalculator.getAverageBlockTint(chunk, neighbourChunks, state, x, y, z)
|
||||
var rendered = model.render(position, mesh, random, state, neighbourBlocks, light, tints)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user