From 745143fab77b792874f44da5ea4865ae56657274 Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Sun, 15 Oct 2023 21:50:35 +0200 Subject: [PATCH] skeletal rotation --- .../resources/model/skeletal/dummy.smodel | 10 +++-- .../skeletal/baked/SkeletalBakeContext.kt | 15 +++---- .../rendering/skeletal/model/SkeletalModel.kt | 5 ++- .../model/elements/SkeletalElement.kt | 14 ++++--- .../skeletal/model/elements/SkeletalFace.kt | 9 +++-- .../model/elements/SkeletalRotation.kt | 40 +++++++++++++++++++ 6 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalRotation.kt diff --git a/src/integration-test/resources/model/skeletal/dummy.smodel b/src/integration-test/resources/model/skeletal/dummy.smodel index 1fbc69e27..928143a46 100644 --- a/src/integration-test/resources/model/skeletal/dummy.smodel +++ b/src/integration-test/resources/model/skeletal/dummy.smodel @@ -3,7 +3,11 @@ "body": { "from": [-8, 0, -8], "to": [8, 16, 8], - "rotation": [-180, 0, 270], + "rotation": { + "value": [-180, 0, 270], + "origin": [0, 8, 0], + "rescale": false + }, "texture": "minosoft:dummy_texture", "transform": "body", "faces": { @@ -17,7 +21,7 @@ "children": { "head1": { "transform": "head", - "origin": [0, 5, 0], + "offset": [0, 5, 0], "from": [-5, 0, -5], "to": [5, 10, 5], "faces": { @@ -30,7 +34,7 @@ }, "head2": { "transform": "head", - "origin": [0, 6, 0], + "offset": [0, 6, 0], "from": [-5, 0, -5], "to": [5, 10, 5], "faces": { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/SkeletalBakeContext.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/SkeletalBakeContext.kt index f632659d8..73a675805 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/SkeletalBakeContext.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/SkeletalBakeContext.kt @@ -14,33 +14,34 @@ package de.bixilon.minosoft.gui.rendering.skeletal.baked import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kutil.collections.CollectionUtil.extend import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalVertexConsumer import de.bixilon.minosoft.gui.rendering.skeletal.model.elements.SkeletalElement +import de.bixilon.minosoft.gui.rendering.skeletal.model.elements.SkeletalRotation import de.bixilon.minosoft.gui.rendering.skeletal.model.textures.SkeletalTextureInstance import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY data class SkeletalBakeContext( val offset: Vec3 = Vec3.EMPTY, - val rotation: Vec3 = Vec3.EMPTY, val inflate: Float = 0.0f, val transparency: Boolean = true, val texture: ResourceLocation? = null, - val transform: BakedSkeletalTransform? = null, + val transform: BakedSkeletalTransform, + val rotations: List = emptyList(), - val transforms: Map, val textures: Map, val consumer: SkeletalVertexConsumer, ) { fun copy(element: SkeletalElement): SkeletalBakeContext { - val offset = this.offset + element.origin - val rotation = this.rotation + element.rotation + val offset = this.offset + (element.offset / 16.0f) val inflate = this.inflate + element.inflate val transparency = this.transparency && element.transparency val texture = element.texture ?: texture - val transform = element.transform?.let { transforms[element.transform] } ?: transform + val rotations = if (element.rotation != null) this.rotations.extend(element.rotation) else this.rotations + val transform = element.transform?.let { transform.children[element.transform] ?: throw IllegalArgumentException("Can not find transform ${element.transform}") } ?: transform - return copy(offset = offset, rotation = rotation, inflate = inflate, transparency = transparency, texture = texture, transform = transform) + return copy(offset = offset, inflate = inflate, transparency = transparency, texture = texture, transform = transform, rotations = rotations) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt index 0faa1a3c0..286298ae9 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.gui.rendering.skeletal.model +import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalMesh @@ -25,6 +26,7 @@ import de.bixilon.minosoft.gui.rendering.skeletal.model.textures.SkeletalTexture import de.bixilon.minosoft.gui.rendering.skeletal.model.transforms.SkeletalTransform import de.bixilon.minosoft.gui.rendering.system.base.texture.shader.ShaderTexture import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY import java.util.concurrent.atomic.AtomicInteger data class SkeletalModel( @@ -58,9 +60,10 @@ data class SkeletalModel( for ((name, transform) in this.transforms) { transforms[name] = transform.bake(AtomicInteger(1)) } + val baseTransform = BakedSkeletalTransform(0, Vec3.EMPTY, transforms) for ((name, element) in elements) { - element.bake(mesh, textures, transforms) + element.bake(mesh, textures, baseTransform) } return BakedSkeletalModel(mesh, transforms) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt index fa726cf36..5cd7d7d2e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt @@ -25,8 +25,8 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY data class SkeletalElement( val from: Vec3, val to: Vec3, - val origin: Vec3 = (from - to) / 2.0f, - val rotation: Vec3 = Vec3.EMPTY, + val offset: Vec3 = Vec3.EMPTY, + val rotation: SkeletalRotation? = null, val inflate: Float = 0.0f, val transparency: Boolean = true, val enabled: Boolean = true, @@ -36,10 +36,14 @@ data class SkeletalElement( val children: Map, ) { - fun bake(mesh: SkeletalMesh, textures: Map, transforms: Map) { + init { + this.rotation?.apply(from, to) + } + + fun bake(mesh: SkeletalMesh, textures: Map, transform: BakedSkeletalTransform) { if (!enabled) return - val context = SkeletalBakeContext(transforms = transforms, textures = textures, consumer = mesh) + val context = SkeletalBakeContext(transform = transform, textures = textures, consumer = mesh) return bake(context) } @@ -47,8 +51,8 @@ data class SkeletalElement( if (!enabled) return val context = context.copy(this) - val transform = context.transform?.id ?: 0 + val transform = context.transform.id for ((direction, face) in faces) { face.bake(context, direction, this, transform) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt index 512927083..80083e4b6 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt @@ -30,16 +30,17 @@ data class SkeletalFace( ) { fun bake(context: SkeletalBakeContext, direction: Directions, element: SkeletalElement, transform: Int) { - val positions = direction.getPositions(context.offset + (element.from / 16.0f - context.inflate), context.offset + (element.to / 16.0f + context.inflate)) + val positions = direction.getPositions(context.offset + element.from - context.inflate, context.offset + element.to + context.inflate) val texture = context.textures[texture ?: context.texture ?: throw IllegalStateException("element has no texture set!")] ?: throw IllegalStateException("Texture not found!") val texturePositions = ModelBakeUtil.getTextureCoordinates(uv.start / texture.properties.resolution, uv.end / texture.properties.resolution) - val origin = element.origin / 16.0f - element.rotation.let { - val rad = -GLM.radians(it) + for (rotation in context.rotations) { + val origin = rotation._origin / 16.0f + + val rad = -GLM.radians(rotation.value) for ((index, position) in positions.withIndex()) { val out = Vec3(position) out.rotateAssign(rad[0], Axes.X, origin, false) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalRotation.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalRotation.kt new file mode 100644 index 000000000..2dcd82acf --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalRotation.kt @@ -0,0 +1,40 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.skeletal.model.elements + +import com.fasterxml.jackson.annotation.JsonIgnore +import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kutil.cast.CastUtil.unsafeNull +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY + +data class SkeletalRotation( + val value: Vec3, + val origin: Vec3? = null, + val rescale: Boolean = false, +) { + @JsonIgnore + var _origin: Vec3 = unsafeNull() + + fun apply(from: Vec3, to: Vec3) { + this._origin = (to - from) / 2.0f + } + + operator fun plus(other: SkeletalRotation): SkeletalRotation { + return SkeletalRotation(this.value + other.value, _origin) + } + + companion object { + val EMPTY = SkeletalRotation(Vec3.EMPTY, Vec3.EMPTY, false) + } +}