From 8a379f2a97c4bc36bc89c27ddc3b8852476d7bdd Mon Sep 17 00:00:00 2001 From: Bixilon Date: Thu, 3 Mar 2022 21:10:30 +0100 Subject: [PATCH] wip skeletal animations --- .../container/BlockSectionDataProvider.kt | 2 +- .../skeletal/baked/BakedSkeletalModel.kt | 8 ++- .../skeletal/instance/SkeletalInstance.kt | 55 +++++++++++-------- .../model/animations/SkeletalAnimation.kt | 24 +++++++- .../animations/animator/SkeletalAnimator.kt | 43 ++++++++++++++- .../animator/keyframes/SkeletalKeyframe.kt | 2 +- 6 files changed, 106 insertions(+), 28 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt b/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt index a6ae65b8c..2d362c6ab 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt @@ -26,7 +26,7 @@ class BlockSectionDataProvider( override fun recalculate() { super.recalculate() - val data: Array = data ?: return // ToDo: ClassCastException + val data: Array = data ?: return fluidCount = 0 for (blockState in data) { 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 32407260e..e6c440791 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 @@ -100,7 +100,11 @@ class BakedSkeletalModel( this.mesh = mesh } - private fun Vec3.fromBlockCoordinates(): Vec3 { - return (this / UnbakedElement.BLOCK_RESOLUTION) + Vec3(0.5f, 0.0f, 0.5f) + companion object { + + fun Vec3.fromBlockCoordinates(): Vec3 { + return Vec3(this.x / UnbakedElement.BLOCK_RESOLUTION + 0.5f, this.y / UnbakedElement.BLOCK_RESOLUTION, this.z / UnbakedElement.BLOCK_RESOLUTION + 0.5f) + } + } } 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 c563c1809..82d651d7b 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 @@ -13,8 +13,11 @@ package de.bixilon.minosoft.gui.rendering.skeletal.instance +import de.bixilon.kutil.time.TimeUtil import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel +import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel.Companion.fromBlockCoordinates +import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.SkeletalAnimation import de.bixilon.minosoft.gui.rendering.system.base.shader.Shader import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3 import glm_.func.rad @@ -28,17 +31,25 @@ class SkeletalInstance( val model: BakedSkeletalModel, ) { private val blockPosition = blockPosition.toVec3 - private var openDelta = -90.0f - private var closing: Boolean? = null + private var currentAnimation: SkeletalAnimation? = null + private var animationTime = 0.0f + private var animationLastFrame = -1L fun playAnimation(name: String) { - if (name.contains("closing")) { - openDelta = -90.0f - closing = true - } else { - openDelta = 0.0f - closing = false + var animation: SkeletalAnimation? = null + for (animationEntry in model.model.animations) { + if (animationEntry.name != name) { + continue + } + animation = animationEntry + break } + if (animation == null) { + throw IllegalArgumentException("Can not find animation $name") + } + animationTime = 0.0f + animationLastFrame = -1L + this.currentAnimation = animation } fun draw() { @@ -53,22 +64,22 @@ class SkeletalInstance( private fun setTransforms(shader: Shader) { val base = Mat4().translateAssign(blockPosition.toVec3) - val origin = Vec3(0 + 8, 10, 7 + 8) / Vec3(16, 16, 16) - val rotationX = (openDelta).rad - if (closing != null) { - if (closing!!) { - openDelta += 2f - } else { - openDelta -= 2f - } - if (openDelta <= -90.0f || openDelta >= 0.0f) { - closing = null - } - } - + val origin = Vec3(0, 10, 7).fromBlockCoordinates() val lid = Mat4() lid.translateAssign(origin) - lid.rotateAssign(-rotationX, Vec3(1, 0, 0)) + + val animation = currentAnimation + if (animation != null) { + val time = TimeUtil.time + if (this.animationLastFrame > 0L) { + val delta = time - this.animationLastFrame + animationTime += delta / 1000.0f + } + animationLastFrame = time + + lid.rotateAssign(-animation.getRotation(animationTime).x.rad, Vec3(1, 0, 0)) + } + lid.translateAssign(-origin) lid[3, 0] += blockPosition.x lid[3, 1] += blockPosition.y diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/SkeletalAnimation.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/SkeletalAnimation.kt index 35c4892d5..48b5de2f4 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/SkeletalAnimation.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/SkeletalAnimation.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.skeletal.model.animations import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animator.SkeletalAnimator +import glm_.vec3.Vec3 import java.util.* data class SkeletalAnimation( @@ -23,4 +24,25 @@ data class SkeletalAnimation( val override: Boolean = false, val length: Float, val animators: Map, -) +) { + fun getRotation(time: Float): Vec3 { + val animator = animators.values.iterator().next() + + var time = time + when (loop) { + AnimationLoops.LOOP -> time % length + AnimationLoops.ONCE -> { + if (time > length) { + time = 0.0f + } + } + AnimationLoops.HOLD -> { + if (time > length) { + time = length + } + } + } + + return animator.getRotation(time) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/SkeletalAnimator.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/SkeletalAnimator.kt index 0ef6e5ba0..f1e1ff6d6 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/SkeletalAnimator.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/SkeletalAnimator.kt @@ -14,9 +14,50 @@ package de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animator import de.bixilon.minosoft.gui.rendering.skeletal.model.animations.animator.keyframes.SkeletalKeyframe +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3 +import glm_.vec3.Vec3 +import kotlin.math.PI +import kotlin.math.sin data class SkeletalAnimator( val name: String, val type: String, // ToDo: enum val keyframes: List, -) +) { + + fun getRotation(time: Float): Vec3 { + var rotation = Vec3.EMPTY + + var firstKeyframe: SkeletalKeyframe? = null + var secondKeyframe: SkeletalKeyframe? = null + + for (keyframe in keyframes) { + if (firstKeyframe == null) { + firstKeyframe = keyframe + continue + } + if (time <= keyframe.time) { + if (secondKeyframe != null) { + firstKeyframe = secondKeyframe + } + secondKeyframe = keyframe + continue + } + break + } + + if (firstKeyframe == null || secondKeyframe == null) { + return rotation + } + + val firstRotation = firstKeyframe.dataPoints[0].toVec3() + val secondRotation = secondKeyframe.dataPoints[0].toVec3() + + val delta = (time - firstKeyframe.time) / (secondKeyframe.time - firstKeyframe.time) + rotation = firstRotation + (secondRotation - firstRotation) * (sin(delta * PI / 2)) + + + return rotation + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/keyframes/SkeletalKeyframe.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/keyframes/SkeletalKeyframe.kt index 6d0a4571e..f66186a7d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/keyframes/SkeletalKeyframe.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/animations/animator/keyframes/SkeletalKeyframe.kt @@ -19,7 +19,7 @@ data class SkeletalKeyframe( val channel: String, // ToDo: enum val dataPoints: List>, val uuid: UUID, - val time: Int, + val time: Float, val interpolation: KeyframeInterpolations = KeyframeInterpolations.LINEAR, )