diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt index 00a23bea3..962bc3f83 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt @@ -189,10 +189,7 @@ class RenderWindow( Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Loading skeletal meshes (after ${stopwatch.labTime()})" } - - for (model in modelLoader.entities.skeletal.values) { - model.loadMesh(this) - } + modelLoader.entities.loadSkeletal() Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Registering callbacks (after ${stopwatch.labTime()})..." } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/SkeletalEntityModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/SkeletalEntityModel.kt index 1e1630dac..c67dd20e7 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/SkeletalEntityModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/SkeletalEntityModel.kt @@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.entity.models import de.bixilon.minosoft.data.entities.entities.Entity import de.bixilon.minosoft.gui.rendering.entity.EntityRenderer +import de.bixilon.minosoft.gui.rendering.skeletal.baked.SkeletalModelStates import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance abstract class SkeletalEntityModel(renderer: EntityRenderer, entity: E) : EntityModel(renderer, entity) { @@ -24,7 +25,10 @@ abstract class SkeletalEntityModel(renderer: EntityRenderer, entity: override fun prepare() { super.prepare() - instance.model.loadMesh(renderWindow) + if (instance.model.state != SkeletalModelStates.LOADED) { + instance.model.preload(renderWindow) // ToDo: load async + instance.model.load() + } } override fun draw() { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt index a8fd5f4ee..e41a62fac 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt @@ -24,7 +24,6 @@ import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalMesh import de.bixilon.minosoft.gui.rendering.skeletal.model.SkeletalModel import de.bixilon.minosoft.gui.rendering.skeletal.model.outliner.SkeletalOutliner import de.bixilon.minosoft.gui.rendering.system.base.texture.ShaderTexture -import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap @@ -35,8 +34,8 @@ class BakedSkeletalModel( val textures: Int2ObjectOpenHashMap, ) { lateinit var mesh: SkeletalMesh - val loaded: Boolean - get() = this::mesh.isInitialized && mesh.state == Mesh.MeshStates.LOADED + var state: SkeletalModelStates = SkeletalModelStates.DECLARED + private set private fun calculateOutlinerMapping(): Map { val mapping: Object2IntOpenHashMap = Object2IntOpenHashMap() @@ -68,10 +67,8 @@ class BakedSkeletalModel( return mapping } - fun loadMesh(renderWindow: RenderWindow) { - if (loaded) { - return - } + fun preload(renderWindow: RenderWindow) { + check(state == SkeletalModelStates.DECLARED) { "Can not preload model in $state" } val mesh = SkeletalMesh(renderWindow, 1000) val outlinerMapping = calculateOutlinerMapping() @@ -118,14 +115,20 @@ class BakedSkeletalModel( } } } - mesh.load() this.mesh = mesh + state = SkeletalModelStates.PRE_LOADED + } + + fun load() { + check(state == SkeletalModelStates.PRE_LOADED) { "Can not load model in state: $state" } + mesh.load() + state = SkeletalModelStates.LOADED } fun unload() { - if (loaded) { - mesh.unload() - } + check(state == SkeletalModelStates.LOADED) { "Can not unload model in state $state" } + mesh.unload() + state = SkeletalModelStates.UNLOADED } companion object { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/SkeletalModelStates.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/SkeletalModelStates.kt new file mode 100644 index 000000000..709dfc085 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/SkeletalModelStates.kt @@ -0,0 +1,22 @@ +/* + * Minosoft + * Copyright (C) 2020-2022 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.skeletal.baked + +enum class SkeletalModelStates { + DECLARED, + PRE_LOADED, + LOADED, + UNLOADED, + ; +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt index 476caaa46..6e611bf00 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt @@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.renderer.drawable.DeltaDrawable import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel +import de.bixilon.minosoft.gui.rendering.skeletal.baked.SkeletalModelStates import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.SkeletalAnimation import de.bixilon.minosoft.gui.rendering.skeletal.model.outliner.SkeletalOutliner import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY @@ -137,6 +138,9 @@ class SkeletalInstance( } fun unload() { - model.unload() + val model = model + if (model.state == SkeletalModelStates.LOADED) { + model.unload() + } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/EntityModels.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/EntityModels.kt index b898442ae..82ed809af 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/EntityModels.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/EntityModels.kt @@ -13,6 +13,8 @@ package de.bixilon.minosoft.gui.rendering.world.entities +import de.bixilon.kutil.concurrent.pool.DefaultThreadPool +import de.bixilon.kutil.latch.CountUpAndDownLatch import de.bixilon.minosoft.assets.util.FileUtil.readJson import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.gui.rendering.RenderWindow @@ -37,4 +39,18 @@ class EntityModels(val renderWindow: RenderWindow) { fun cleanup() { unbakedModels.clear() } + + fun loadSkeletal() { + val latch = CountUpAndDownLatch(1) + for (model in skeletal.values) { + latch.inc() + DefaultThreadPool += { model.preload(renderWindow); latch.dec() } + } + latch.dec() + latch.await() + + for (model in skeletal.values) { + model.load() + } + } }