fix yaw interpolation, use circle constants

This commit is contained in:
Bixilon 2023-05-31 20:24:12 +02:00
parent 62e68b2352
commit 2ee51a76e7
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
8 changed files with 87 additions and 13 deletions

View File

@ -28,8 +28,8 @@ data class YawRotation(
}
companion object : EntityTargetPropertyFactory<YawRotation> {
const val MIN = -180.0f
const val MAX = 180.0f
const val MIN = -EntityRotation.HALF_CIRCLE_DEGREE
const val MAX = EntityRotation.HALF_CIRCLE_DEGREE
override val name: String = "y_rotation"
private val parser = FloatRangeParser(null)

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.data.entities
import de.bixilon.kotlinglm.vec3.Vec3d
import de.bixilon.kutil.math.interpolation.FloatInterpolation.interpolateLinear
import de.bixilon.minosoft.data.Tickable
import de.bixilon.minosoft.data.entities.EntityRotation.Companion.interpolateYaw
import de.bixilon.minosoft.data.entities.entities.Entity
import de.bixilon.minosoft.data.registries.shapes.aabb.AABB
import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable
@ -66,11 +67,11 @@ class EntityRenderInfo(private val entity: Entity) : Drawable, Tickable {
private fun interpolateRotation(delta: Float) {
val rotation1 = this.rotation1
if (rotation === rotation1) {
if (rotation == rotation1) {
return
}
val rotation0 = this.rotation0
rotation = EntityRotation(interpolateLinear(delta, rotation0.yaw, rotation1.yaw), interpolateLinear(delta, rotation0.pitch, rotation1.pitch))
rotation = EntityRotation(interpolateYaw(delta, rotation0.yaw, rotation1.yaw), interpolateLinear(delta, rotation0.pitch, rotation1.pitch))
}
override fun draw(millis: Long) {

View File

@ -16,6 +16,8 @@ import de.bixilon.kotlinglm.func.cos
import de.bixilon.kotlinglm.func.rad
import de.bixilon.kotlinglm.func.sin
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kutil.math.interpolation.FloatInterpolation.interpolateLinear
import kotlin.math.abs
data class EntityRotation(
val yaw: Float,
@ -33,6 +35,24 @@ data class EntityRotation(
}
companion object {
const val CIRCLE_DEGREE = 360
const val HALF_CIRCLE_DEGREE = 180
val EMPTY = EntityRotation(0.0f, 0.0f)
fun interpolateYaw(delta: Float, start: Float, end: Float): Float {
if (delta <= 0.0) return start
if (delta >= 1.0) return end
var end = end
if (abs(end - start) > HALF_CIRCLE_DEGREE) {
end += if (start > end) CIRCLE_DEGREE else -CIRCLE_DEGREE
}
val i = interpolateLinear(delta, start, end)
return (i + HALF_CIRCLE_DEGREE) % CIRCLE_DEGREE - HALF_CIRCLE_DEGREE
}
}
}

View File

@ -19,6 +19,8 @@ import de.bixilon.minosoft.config.key.KeyActions
import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.entities.EntityRotation
import de.bixilon.minosoft.data.entities.EntityRotation.Companion.CIRCLE_DEGREE
import de.bixilon.minosoft.data.entities.EntityRotation.Companion.HALF_CIRCLE_DEGREE
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.camera.MatrixHandler
import de.bixilon.minosoft.input.camera.MovementInputActions
@ -114,12 +116,12 @@ class CameraInput(
fun calculateRotation(delta: Vec2d, rotation: EntityRotation): EntityRotation {
val delta = delta * 0.1f * controlsProfile.mouse.sensitivity
var yaw = delta.x + rotation.yaw
if (yaw > 180) {
yaw -= 360
} else if (yaw < -180) {
yaw += 360
if (yaw > HALF_CIRCLE_DEGREE) {
yaw -= CIRCLE_DEGREE
} else if (yaw < -HALF_CIRCLE_DEGREE) {
yaw += CIRCLE_DEGREE
}
yaw %= 180
yaw %= HALF_CIRCLE_DEGREE
val pitch = GLM.clamp(delta.y + rotation.pitch, -89.9, 89.9)
return EntityRotation(yaw.toFloat(), pitch.toFloat())
}

View File

@ -75,8 +75,8 @@ class SkeletalInstance(
fun updatePosition(position: Vec3d, rotation: EntityRotation) {
val matrix = Mat4()
.translateAssign(Vec3(position - context.camera.offset.offset))
.rotateAssign((180.0f - rotation.yaw).rad, Vec3(0, 1, 0))
.translateAssign(Vec3(-0.5, 0.0f, -0.5)) // move to bottom center
.rotateAssign((EntityRotation.HALF_CIRCLE_DEGREE - rotation.yaw).rad, Y_ROTATION_VECTOR)
.translateAssign(CENTER_OFFSET) // move to bottom center
if (baseTransform != matrix) {
baseTransform = matrix
@ -140,4 +140,9 @@ class SkeletalInstance(
model.unload()
}
}
companion object {
private val CENTER_OFFSET = Vec3(-0.5, 0.0f, -0.5)
private val Y_ROTATION_VECTOR = Vec3(0, 1, 0)
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.sky.planet
import de.bixilon.kutil.hash.HashUtil.murmur64
import de.bixilon.kutil.random.RandomUtil.nextFloat
import de.bixilon.minosoft.data.entities.EntityRotation.Companion.CIRCLE_DEGREE
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.world.time.DayPhases
import de.bixilon.minosoft.gui.rendering.sky.SkyRenderer
@ -37,7 +38,7 @@ class SunRenderer(
// 180: night (13k-23k)
return ((time.time / ProtocolDefinition.TICKS_PER_DAYf) - 0.25f) * 360.0f
return ((time.time / ProtocolDefinition.TICKS_PER_DAYf) - 0.25f) * CIRCLE_DEGREE
}
override fun calculateIntensity(): Float {

View File

@ -19,12 +19,14 @@ import de.bixilon.minosoft.data.text.formatting.color.RGBColor;
import java.util.regex.Pattern;
import static de.bixilon.minosoft.data.entities.EntityRotation.CIRCLE_DEGREE;
public final class ProtocolDefinition {
public static final int STRING_MAX_LENGTH = 32767;
public static final int DEFAULT_PORT = 25565;
public static final int SOCKET_TIMEOUT = 30000;
public static final int STATUS_PROTOCOL_PACKET_MAX_SIZE = 1 << 16;
public static final float ROTATION_ANGLE_DIVIDER = 360.0F / 256.0F;
public static final float ROTATION_ANGLE_DIVIDER = CIRCLE_DEGREE / 256.0F;
public static final float SOUND_PITCH_DIVIDER = 100.0F / 63.0F;

View File

@ -0,0 +1,43 @@
package de.bixilon.minosoft.data.entities
import de.bixilon.minosoft.data.entities.EntityRotation.Companion.interpolateYaw
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class EntityRotationTest {
@Test
fun interpolation1() {
assertEquals(50.0f, interpolateYaw(0.5f, 0.0f, 100.0f))
}
@Test
fun interpolation2() {
assertEquals(0.0f, interpolateYaw(-1.0f, 0.0f, 100.0f))
}
@Test
fun interpolation3() {
assertEquals(100.0f, interpolateYaw(2.0f, 0.0f, 100.0f))
}
@Test
fun interpolation4() {
assertEquals(-180.0f, interpolateYaw(0.1f, 180.0f, -180.0f))
}
@Test
fun interpolation5() {
assertEquals(-180.0f, interpolateYaw(0.9f, 180.0f, -180.0f))
}
@Test
fun interpolation6() {
assertEquals(-170.0f, interpolateYaw(0.5f, 180.0f, -160.0f))
}
@Test
fun interpolation7() {
assertEquals(150.0f, interpolateYaw(0.5f, 110.0f, -170.0f))
}
}