wip skeletal animations

This commit is contained in:
Bixilon 2022-03-03 21:10:30 +01:00
parent 7679e4e012
commit 8a379f2a97
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
6 changed files with 106 additions and 28 deletions

View File

@ -26,7 +26,7 @@ class BlockSectionDataProvider(
override fun recalculate() {
super.recalculate()
val data: Array<Any?> = data ?: return // ToDo: ClassCastException
val data: Array<Any?> = data ?: return
fluidCount = 0
for (blockState in data) {

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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<UUID, SkeletalAnimator>,
)
) {
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)
}
}

View File

@ -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<SkeletalKeyframe>,
)
) {
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
}
}

View File

@ -19,7 +19,7 @@ data class SkeletalKeyframe(
val channel: String, // ToDo: enum
val dataPoints: List<Map<String, Any>>,
val uuid: UUID,
val time: Int,
val time: Float,
val interpolation: KeyframeInterpolations = KeyframeInterpolations.LINEAR,
)