mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 20:05:02 -04:00
wip skeletal animations
This commit is contained in:
parent
7679e4e012
commit
8a379f2a97
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user