skeletal: animation instancing

This commit is contained in:
Moritz Zwerger 2023-10-17 10:14:16 +02:00
parent 6a55f94424
commit a0a52f57b4
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
12 changed files with 200 additions and 50 deletions

View File

@ -67,12 +67,11 @@
}
},
"animations": {
"open": {
"open": [
{
"transform": "head",
"loop": "hold",
"length": 0.3,
"animators": [
{
"transform": "base.head",
"keyframes": [
{
"type": "rotate",
@ -87,4 +86,3 @@
]
}
}
}

View File

@ -13,10 +13,8 @@
package de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.entities.block.container.storage.StorageBlockEntity
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
@ -33,11 +31,11 @@ abstract class StorageBlockEntityRenderer<E : StorageBlockEntity>(
@Deprecated("refactor")
fun playOpen() {
TODO()
skeletal?.animation?.play("open")
}
@Deprecated("refactor")
fun playClose() {
TODO()
skeletal?.animation?.play("close")
}
}

View File

@ -16,12 +16,13 @@ package de.bixilon.minosoft.gui.rendering.skeletal.baked
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalMesh
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.SkeletalAnimation
data class BakedSkeletalModel(
val mesh: SkeletalMesh,
val transform: BakedSkeletalTransform,
val transformCount: Int,
// TODO: animations
val animations: Map<String, SkeletalAnimation>,
) {
private var state = SkeletalModelStates.DECLARED

View File

@ -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.skeletal.baked.animation
interface AbstractAnimation {
fun draw(delta: Float): Boolean
}

View File

@ -0,0 +1,25 @@
/*
* 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.skeletal.baked.animation.keyframe
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.AbstractAnimation
class KeyframeAnimation(
val animators: Array<KeyframeAnimator>,
) : AbstractAnimation {
override fun draw(delta: Float): Boolean {
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,25 @@
/*
* 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.skeletal.baked.animation.keyframe
import de.bixilon.minosoft.gui.rendering.skeletal.instance.TransformInstance
import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animators.AnimationLoops
import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animators.keyframes.SkeletalKeyframe
class KeyframeAnimator(
val transform: TransformInstance,
val loop: AnimationLoops,
val length: Float,
val keyframes: List<SkeletalKeyframe>,
)

View File

@ -0,0 +1,50 @@
/*
* 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.skeletal.instance
import de.bixilon.kutil.time.TimeUtil.nanos
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.AbstractAnimation
class AnimationManager(val instance: SkeletalInstance) {
private var lastDraw = -1L
fun play(animation: AbstractAnimation) {
// TODO: don't play animations twice, reset them?
}
fun play(name: String) {
val animation = instance.model.animations[name] ?: throw IllegalArgumentException("Can not find animation $name!")
play(animation.instance(instance))
}
fun stop(animation: AbstractAnimation) {
// TODO
}
fun stop(name: String) {
// TODO
}
fun draw() {
val nanos = nanos()
val delta = nanos - lastDraw
draw(delta / 1000.0f)
}
fun draw(delta: Float) {
// TODO
}
}

View File

@ -28,9 +28,12 @@ class SkeletalInstance(
val model: BakedSkeletalModel,
val transform: TransformInstance,
) {
val animation = AnimationManager(this)
var light = 0xFF
fun draw() {
animation.draw()
context.skeletal.draw(this, light)
}

View File

@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger
data class SkeletalModel(
val elements: Map<String, SkeletalElement>,
val textures: Map<ResourceLocation, SkeletalTexture>,
val animations: Map<ResourceLocation, SkeletalAnimation>,
val animations: Map<String, SkeletalAnimation>,
val transforms: Map<String, SkeletalTransform>,
) {
val loadedTextures: MutableMap<ResourceLocation, SkeletalTextureInstance> = mutableMapOf()
@ -74,6 +74,6 @@ data class SkeletalModel(
element.bake(mesh, textures, baseTransform)
}
return BakedSkeletalModel(mesh, baseTransform, transformId.get())
return BakedSkeletalModel(mesh, baseTransform, transformId.get(), animations)
}
}

View File

@ -13,11 +13,21 @@
package de.bixilon.minosoft.gui.rendering.skeletal.model.animations
import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animators.AnimationLoops
import com.fasterxml.jackson.annotation.JsonValue
import de.bixilon.kutil.array.ArrayUtil.cast
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.KeyframeAnimation
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.KeyframeAnimator
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animators.SkeletalAnimator
class SkeletalAnimation(
val loop: AnimationLoops,
val length: Float,
val animators: List<SkeletalAnimator>
)
class SkeletalAnimation(@JsonValue val animators: List<SkeletalAnimator>) {
fun instance(instance: SkeletalInstance): KeyframeAnimation {
val array: Array<KeyframeAnimator?> = arrayOfNulls(this.animators.size)
for ((index, animator) in this.animators.withIndex()) {
array[index] = animator.instance(instance)
}
return KeyframeAnimation(array.cast())
}
}

View File

@ -13,9 +13,32 @@
package de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animators
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.KeyframeAnimator
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
import de.bixilon.minosoft.gui.rendering.skeletal.instance.TransformInstance
import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animators.keyframes.SkeletalKeyframe
data class SkeletalAnimator(
val transform: String,
val loop: AnimationLoops,
val length: Float,
val keyframes: List<SkeletalKeyframe>,
)
) {
private val split = transform.split(".", "/").toTypedArray()
private fun SkeletalInstance.getTransform(): TransformInstance {
var transform = this.transform
if (split.size == 1 && split[0] == "base") return transform
for (name in split) {
transform = transform.children[name] ?: throw IllegalStateException("Animation is referencing unknown transform!")
}
return transform
}
fun instance(instance: SkeletalInstance): KeyframeAnimator {
val transform = instance.getTransform()
return KeyframeAnimator(transform, loop, length, keyframes)
}
}

View File

@ -75,12 +75,11 @@
}
]
},
"close": {
"loop": "hold",
"length": 0.5,
"animators": [
"close": [
{
"transform": "base.lid",
"loop": "hold",
"length": 0.5,
"keyframes": [
{
"type": "rotate",
@ -95,4 +94,3 @@
]
}
}
}